/srv/irclogs.ubuntu.com/2013/08/16/#juju-dev.txt

bigjoolsapps should not be rotating their own logs00:00
bigjoolstwisted tried that and it was miserably shit00:00
davecheneybigjools: was talking about reopening on HUP00:00
thumperwallyworld_: aren't you off today?00:57
wallyworld_thumper: yeah, about to go to in00:57
axwthumper: if someone "not lgtm"s something, I need that same person to lgtm to go ahead - is that right?01:00
thumperaxw: it depends :)01:01
thumperaxw: what is it?01:01
axwjust a sec01:01
axwthumper: https://codereview.appspot.com/12924043/01:01
* thumper looks01:01
davecheneyaxw: depends, could you take them in a straight fight ?01:02
axwheh :)01:02
thumperaxw: if you can address my comments, I can give you an LGTM01:11
thumperaxw: william's opposition was due to no test, since you've added one, I think you'll be fine01:11
* thumper goes to check on the pizza in the oven01:11
axwthumper: thanks01:12
axwthumper: that LC_ALL thing is existing. do you want me to update those things as I go?01:16
thumper:) do you feel like making it more up to date?01:17
axw... yes01:17
axw:)01:17
axwI think I'll write a tool to check import groups01:22
axwprevent myself from submitting crap01:22
davecheneyhttps://bugs.launchpad.net/juju-core/+bug/121290301:26
_mup_Bug #1212903: cmd/juju: debug hooks should set a better PS1 <papercut> <juju-core:New> <https://launchpad.net/bugs/1212903>01:26
thumperaxw: That bug ^^^ seems pretty trivial to do right?01:34
* axw looks01:34
axwthumper: yes should be pretty simple01:35
axwI'll take a look in a moment01:37
davecheneythumper: axw yeah01:39
davecheneyit would be super useful to have for our upcoming engagements01:39
davecheneywe're always zooming the screen01:39
davecheneythen the tmux output and the path become a real issue01:39
davecheneyfor a charm the standard path consumes almost all the screen width01:40
thumperdavecheney: I fully agree with the bug description01:40
thumperI think it is sound01:41
davecheneysweet01:41
davecheneyi didn't think it would be a technical issue to fix01:41
davecheneymore ... philosophical01:41
thumperaxw: you aren't looking at breaking up the agent config are you?02:13
thumperaxw: because if you aren't, I'll take that on02:13
axwthumper: not right now02:13
axwokey dokey02:13
thumperI kinda need it for some other work02:13
axwthumper: nps. I'll work on bugs and continue with the manual provisioner02:14
thumperas after talking with william, he convinced me that shoving env vars into the upstart scripts isn't very good02:14
axwheh ok :)02:14
thumperrewriting upstart scripts on upgrade is a little crazy02:14
thumperbut adding stuff to agent config isn't too bad02:14
axwright02:14
* thumper recalls the need to write an email about juju containers02:16
davecheneyhttps://bugs.launchpad.net/juju-core/+bug/121291602:48
_mup_Bug #1212916: uniter/worker: unit agent MUST remove stale unix socket <papercut> <juju-core:New> <https://launchpad.net/bugs/1212916>02:48
thumperdavecheney: if you put an importance on the bug, please mark it triaged02:56
davecheneythumper: will do02:57
davecheneysorry02:57
davecheneywill fix02:57
thumperdavecheney: I've done those two02:57
thumperbut for future reference02:57
davecheneyok, i understand now02:57
axwthumper: thanks, I've updated checkers -> jc. will merge03:00
thumperaxw: ack03:33
thumperaxw: if you run the trunk tests, do your ec2 ones pass?03:50
* thumper wonders if goamz has been updated03:50
axwthumper: goamz has indeed been updated03:50
axware you getting a TestInstanceState failure?03:50
thumperyes03:51
* thumper pulls goamz and tries again03:51
axwI'll send an email now. Sorry, should have done it last week03:51
thumperI am prepared to buy drinks for whoever makes the ec2 tests run faster (without skipping or producing incorrect results)03:52
axwthumper: rogpeppe said he sped it down to 6s or something like that03:52
thumperbut decided not to commit it?03:52
axwIIRC it required modifying goamz itself03:52
axwI think there's some global variable that would affect the normal operation03:52
thumperwell, if he fixes it, I'll buy him some drinks :)03:52
davecheneyhttps://bugs.launchpad.net/juju-core/+bug/121293604:36
_mup_Bug #1212936: cmd/juju: debug-hooks without hook fired should place the user into a simple hook environment <papercut> <juju-core:Triaged> <https://launchpad.net/bugs/1212936>04:36
davecheneyrelation question05:39
davecheneycan you run the relation-get hook command during the relation-departed hook ?05:39
rogpeppemornin' all06:12
axwmorning rogpeppe06:22
rogpeppeaxw: hiya06:22
=== tasdomas_afk is now known as tasdomas
noodles775dimitern: Hi! If you have a few minutes at some point, can you read what I tried RE testing with RegisterControlPoint etc on the decscription of https://codereview.appspot.com/12795045/ , and let me know what I have missed, or whether it's something that needs to be added to goose?07:24
dimiternnoodles775: I think an update to goose is in order, so that you can tweak the instance state in the test double07:37
dimiternnoodles775: sorry, I was wrong that you can tweak it without code changes07:37
noodles775dimitern: k - do you think I should do that before landing that branch (ie. so it doesn't land without tests), or it's OK as is?07:40
=== racedo` is now known as racedo
dimiternnoodles775: I don't think increasing the timeout fixes anything07:42
dimiternnoodles775: it's still fragile07:42
dimiternnoodles775: if anything, we should fix the nova server filter to be smarter and return stuff not only in ACTIVE or BUILD states, but also hp-cloud specific BUILD(spawning)07:43
noodles775dimitern: Yeah, I did try that, but it's still fragile (takes about 8-9 seconds to get to BUILD(spawning) from my testing)07:44
dimiternnoodles775: and to test it, you'll need to change goose to allow you to change the instance state when you start a server with the test double07:44
dimiternnoodles775: ok, let me rephrase - timeout by itself is not enough to fix it, you'll need the above things as well07:45
dimiternnoodles775: fixing the filter to use HasPrefix instead of == should be trivial07:47
noodles775dimitern: That doesn't work - I tried that (see the description).07:47
dimiternnoodles775: it doesn't work, because it returns BUILD(networking) and at that state the instance is not yet accessible?07:48
noodles775dimitern: It means that it returns as soon as HP sets BUILD(networking), but juju-core then never connects (I didn't dig deeper, but I assume we make some assumptions)...07:48
noodles775Yes.07:48
dimiternwell, it seems obvious that the network is not yet up at that point07:48
noodles775Right - but it continues to not connect. Let me paste you output, it may make more sense.07:49
=== tasdomas is now known as tasdomas_afk
=== tasdomas_afk is now known as tasdomas
noodles775dimitern: http://paste.ubuntu.com/5991914/07:58
dimiternnoodles775: my point is, instead of HasPrefix, you could use server.Status == nova.StatusBuild || serverStatus == "BUILD(spawning)" (perhaps even define this as const HPStatusBuildSpawning)08:00
dimiternnoodles775: then run it 10 times or more to see if it passes every time, if sometimes it doesn't, then increase the timeout08:01
noodles775dimitern: Right, I did do that and it then takes about 8-9 seconds - so it is better than 15s that it takes for ACTIVE. If you think it's better to use that way, I'll do that.08:01
dimiternnoodles775: the hp-specific build const should be definied in goose, like other nova.Status* consts I think, and a change to enable setting it in the double is in order, so you can test it08:02
noodles775dimitern: yep, will do.08:03
dimiternnoodles775: thanks!08:03
noodles775dimitern: np, thanks for the feedback and direction.08:03
dimiternrogpeppe: hey08:03
rogpeppedimitern: hiya08:03
dimiternnoodles775: no worries, glad I can help08:03
dimiternrogpeppe: updated https://codereview.appspot.com/12990043/08:03
rogpeppedimitern: looking08:03
dimiternrogpeppe: cheers08:03
rogpeppedimitern: reviewed08:13
dimiternrogpeppe: thanks08:15
dimiternfwereade: ping08:15
dimiternblast.. william is out today08:17
dimiternrogpeppe: I have a question08:17
* rogpeppe is all ears08:17
dimiternrogpeppe: now that I changed Relation() to return only the endpoint of the auth'ed unit, should it return []params.Endpoint at all or just a single one?08:17
rogpeppedimitern: hmm, since there can only be one local endpoint, i think it should just return a single one08:18
dimiternrogpeppe: then I shouldn't really use params.RelationInfo, but a copy of it without the Endpoints slice, just a single field08:18
rogpeppedimitern: i suppose so, but i can't get too worried about it.08:21
rogpeppedimitern: the comment in UniterAPI.Relation should definitely be updated though - i missed that08:21
dimiternrogpeppe: ok08:21
dimiternrogpeppe: did you have time to check the charm store for possible relation names?08:23
rogpeppedimitern: no, i'm going to do that this morning08:24
dimiternrogpeppe: great08:24
rogpeppedimitern: i've also been trying to make some sort of sense of the config mess this morning. this is as far as i've got: https://docs.google.com/a/canonical.com/spreadsheet/ccc?key=0AghcHASXWzXmdHdOX2htQVJITkdaYVh4VnZ2Z0RrQWc#gid=008:25
dimiternrogpeppe: looking08:25
rvbaAnyone up for a tiny review? https://codereview.appspot.com/12850045/08:25
rogpeppervba: looking08:25
rogpeppervba: LGTM08:27
rvbarogpeppe: ta08:27
dimiternrogpeppe: for openstack, the username, password and tenant-name are not generated, only the password is secret; auth-url and auth-mode are cloud-specific and not generated, access-key and secret-key are used with auth-keypair only (otherwise username/password are used) - both secret, region is cloud-specific, not generated or secret, both buckets can be generated and are not secret08:34
rogpeppedimitern: feel free to change the spreadsheet!08:35
dimiternrogpeppe: ah, I wasn't sure I can08:35
rogpeppedimitern: if you're logged into your canonical account, you should be able to08:35
dimiternrogpeppe: yeah, I'm already half way through08:42
rogpeppedimitern: yeah, i saw that - very helpful, thanks!08:42
rogpeppervba: if you have a moment at some point, could you perhaps fill out some of the azure-specific entries in this spreadsheet? https://docs.google.com/a/canonical.com/spreadsheet/ccc?key=0AghcHASXWzXmdHdOX2htQVJITkdaYVh4VnZ2Z0RrQWc#gid=008:44
rogpeppervba: i'm trying to start rationalising our config attribute twistiness08:44
rvbarogpeppe: sure, I'll have a look.08:46
rogpeppedoes anyone know how to use the new charm browser to list all available charms?08:51
rogpeppethe old one was easy enough to screen scrape, but this one isn't so easy.08:51
dimiternrogpeppe: not sure about the last 4 columns though08:51
rogpeppedimitern: "needed for sync tools" is whether an attribute is needed when pushing to the private storage08:52
rogpeppedimitern: "needed for bootstrap" is whether the attribute needs to be passed into the bootstrap node08:53
rogpeppedimitern: "needed for client operations after bootstrap" is whether you need to use the attribute when connecting to the state later.08:53
dimiternrogpeppe: I have to think about all of these - all in all they seem to be the same as for ec2, but have to check08:54
rogpeppedimitern: i would expect them to be similar08:54
=== tasdomas is now known as tasdomas_afk
=== tasdomas_afk is now known as tasdomas
rvbarogpeppe: what does "OK to specify in environments.yaml?" mean exactly?09:19
rogpeppervba: do you want a user to be able to specify that attribute in the environments.yaml file?09:19
rogpeppervba: in your case, the answer is likely to be yes for all09:19
rvbaOkay.09:20
rogpeppervba: we have some weird attributes like agent-version, which don't really make sense for a user to be able to specify there09:20
rogpeppervba: that's part of the twistiness09:20
rvbarogpeppe: I see.09:20
rvbarogpeppe: I'm a bit confused by "Cloud account information?".  I interpret this as "The value part of one's cloud account information" but I see ec2's 'region' is checked (with a question mark though).09:36
rogpeppervba: it's whether the attribute should be considered part of the cloud account information (we're planning to move towards specifying cloud accounts as a separate entry in the juju conf file)09:37
rogpeppervba: just leave it blank if you're not sure09:37
rvbarogpeppe: 'region' does not seem to be part of the cloud account information then… it's more linked to the deployment isn't it?09:38
rogpeppervba: yes, you're probably right.09:39
rogpeppervba: i'm not quite sure of fwereade's conception of accounts though09:39
rogpeppefwereade: you should be interested in this too BTW: https://docs.google.com/a/canonical.com/spreadsheet/ccc?key=0AghcHASXWzXmdHdOX2htQVJITkdaYVh4VnZ2Z0RrQWc#gid=009:39
rvbarogpeppe: okay, ta.  I'll put X? then.09:40
rogpeppervba: sgtm09:40
fwereaderogpeppe, rvba: really briefly, because I'm out today: an account is essentially <reference to cloud info> + <auth info> + <possible overrides to cloud info>09:40
fwereaderogpeppe, oh, nice spreadsheet09:41
rogpeppefwereade: so would the ec2 region be part of an account?09:41
fwereaderogpeppe, might be, if someone almost always wants to use (say) eu-west-109:42
fwereaderogpeppe, that's one of those ugly things that really needs to be available for override at env and account level09:43
rogpeppefwereade: is the idea to be able to specify *any* attribute at account level?09:43
fwereaderogpeppe, I don't think we can have a coherent model without allowing that, upsetting though it may be09:44
fwereaderogpeppe, but I don't think it's too painful to just pass unknown keys up levels until they're found to be comprehensible09:44
rogpeppefwereade: hmm, so it's not really "account" - it's more like "environment superclass"09:44
fwereaderogpeppe, I don't personally see that as a particularly useful conception of it, but I expect mileage legitimately varies09:45
rogpeppefwereade: or, i guess "environment template"09:45
fwereaderogpeppe, no, I don't think so...09:46
rogpeppefwereade: i don't really see anything particularly account-like about it, that's all09:46
fwereaderogpeppe, the env may contribute attrs to the account, not vice versa09:46
fwereaderogpeppe, the auth info is the critical bit09:46
fwereaderogpeppe, that's the stuff that has to be included at that level09:46
rogpeppefwereade: erm, surely we're saying that the account can contribute attrs to the env too, no?09:46
fwereaderogpeppe, how is region anything to do with the environment?09:47
fwereaderogpeppe, it's all about the cloud09:47
fwereaderogpeppe, but it can be specified differently at more specific levels09:47
rogpeppefwereade: ah09:47
rogpeppefwereade: so we've really got three levels, "account", "cloud" and "environment"09:47
fwereaderogpeppe, it's definitely a surprising model from our existing perspective but it really holds together pretty well when you think about it enough, I think09:48
rogpeppefwereade: but... are you conflating "account" and "cloud"?09:48
rogpeppefwereade: i find it surprising that i can specify a region in something called an "account", which sounds like it's just got user credentials in it09:49
rogpeppefwereade: it feels a bit like the responsibilities are mixed up there09:50
fwereaderogpeppe, the names indicate what must be specified, the other bits that *can* be specified are about convenience for users (and, yeah, some degree of irritating conceptual bleed for us developers)09:51
rogpeppefwereade: i'm no longer sure how many levels of inheritance we're aiming for here09:52
rogpeppefwereade: i'm not sure it's just a conceptual difficulty for developers - i'd find it awkward to explain to a user too.09:54
fwereaderogpeppe, it's not the environment inheriting from the account inheriting from the cloud -- it's the environment overwriting values on the account overwriting values on the cloud09:54
rogpeppefwereade: i'm not sure i see the difference there09:54
fwereaderogpeppe, inheritance implies an env is an account is a cloud09:56
fwereaderogpeppe, it's rather more like embedding, I think09:56
rogpeppefwereade: if i can specify all the env attrs on an account or a cloud, i'm not sure i see there is a difference09:56
* fwereade is neglecting his family09:56
rogpeppefwereade: right, go away! :-)09:56
rogpeppefwereade: sorry for distracting you09:57
fwereaderogpeppe, (when did I say you could specify an env attr on an account? I don't *think* it needs to flow that way too)09:57
rogpeppefwereade: hmm, i'd thought the env ended up with all the attributes from the account09:58
fwereaderogpeppe, I think that the env ends up with an account (which may have had overrides applied to it), and the *env* only has a few juju-level things set -- one of which is the account09:59
rogpeppefwereade: but are we allowing users to specify a "cloud" thing as well as an environment and an account?09:59
fwereaderogpeppe, because of private clouds essentially09:59
fwereaderogpeppe, most of the time all that tedious cloud stuff comes from simplestreams, so account specification is trivial09:59
rogpeppefwereade: an account specifies a cloud too?10:00
fwereaderogpeppe, sometimes it needs to be hand-specified, and we (1) don't want to dirty up the account specification and (2) may well have a couple of accounts on the same cloud for say testing/staging/production10:00
fwereaderogpeppe, yes, account = <cloud reference> + <auth info> + <possible cloud overrides for convenience>10:01
fwereaderogpeppe, env  = <account reference> + <juju info> + <possible account overrides for convenience>10:01
* fwereade is really off now, and hopes the model makes some sort of sense10:02
* rogpeppe thinks about it10:02
rogpeppefwereade: thanks10:02
rogpeppehmm, that's a first for me - laptop just spontaneously rebooted. i wasn't doing anything significant at the time10:33
* rogpeppe tries to recollect all the threads10:33
dimiternrogpeppe: it happens to me sometimes since I upgraded to raring - all due to video drivers10:34
rogpeppedimitern: yeah, i reckon that's likely to be the problem10:35
dimiternrogpeppe: btw, should we have an EnvironConfig() call in the uniter API? the uniter uses it, but I remember there were some concerns about it10:35
rogpeppedimitern: i also get a weird thing occasionally where everything goes ultra slowly10:35
rogpeppedimitern: what is the uniter using it for?10:35
* dimitern checks10:35
dimiternrogpeppe: to get the provider type and from then the private address10:36
dimiternrogpeppe: and public10:36
rogpeppedimitern: i think you should just have a ProviderType API call10:37
dimiternrogpeppe: ok10:37
natefinchmorning all11:13
rogpeppedimitern: here's the list of all the relation names used in the 193 charms i could find in the charm store, most frequent first: http://paste.ubuntu.com/5992327/11:13
rogpeppenatefinch: hiya11:13
rogpeppedimitern: looks like we can be quite restrictive without it being a problem11:14
dimiternrogpeppe: so it looks like ([a-z-]+)+ should be enough?11:15
dimiternrogpeppe: or more like ([a-z]+-?)+, except it shouldn't end with -11:16
natefinchmgz: I was looking at maas and azure for addressability. I have some code for azure, but it's pretty ugly... I couldn't find where maas was exposing IPs, though11:16
rogpeppedimitern: i think i'd go for [a-z][a-z0-9]*(-[a-z0-9]+)*11:16
dimiternrogpeppe: sgtm11:17
rogpeppedimitern: in case you're interested, i downloaded all the charms with this: http://paste.ubuntu.com/5992345/ (unfortunately obtaining the list of charms was a bit more hassle)11:18
rogpeppedimitern: and i got it to spew out the relation names with this: http://paste.ubuntu.com/5992349/11:18
rogpeppedimitern: (i ran it with this command line: http://paste.ubuntu.com/5992351/)11:20
rogpeppedimitern: so that command is also potentially useful for other charm metadata analysis we might want to do11:20
dimiternrogpeppe: cool! so you didn't miss anything11:20
mgznatefinch: for maas, you might want to ask one of the red squad guys11:20
rogpeppedimitern: well, i might well have missed some charms11:20
mgzwe need a different mechanism for the local provider currently, we might need one for maas too, but I think when I looked at it there seemed to be a reasonable way11:21
mgzstandup guys?11:33
geme_juju-core 1.13.1 won't bootstrap on private openstack. /var/log/cloud-init-output.log reports : ERROR juju open.go:89 state: connection failed, will retry: dial tcp 127.0.0.1:37017: connection refused. There's nothing running on this port.mongod is running on 27017 and 28017 though11:59
mgzgeme_: you need to ssh into the state server machine and look at the juju logs12:07
mgzI had a similar issue a while back, but I'm failing to find or recall what the root cause was12:08
geme_which log ?12:08
mgzlook at things under /var/log/juju12:08
mgzthere's also a mongo log that I remember looking at...12:10
mgzgah, I remember talking to jam about it, but can't find it in the chat logs anywhere12:13
mgzgeme_: any luck? the first few lines of /var/log/juju/machine-0.log should be about mongo state connection12:18
geme_mgz, there is no machine-0.log - just an empty all-machines.log12:20
mgzokay, so can you pastebin your whole cloud-init please? seems the agent didn't get started at all12:20
geme_cloud-init.log and cloud-init-output.log ?12:21
mgz-output please12:22
geme_mgz, jusr seen : 2013-08-16 10:36:05,970 - cc_apt_update_upgrade.py[WARNING]: Source Error: ppa:juju/experimental:add-apt-repository failed12:26
mgzwhat do you get if you sudo run thant command from the box now?12:27
geme_mgz, http://paste.ubuntu.com/5992536/12:33
mgzoh god, that statecert logging12:34
mgzgeme_: okay, so it installs the wrong version of mongodb (2.0.4-1ubuntu2.1) because the repo add failed12:35
geme_adding the repo works from the cmdline12:36
geme_though it needs a return response12:37
mgzmeh, and it's a bare except clause in cloudinit/config/cc_apt_update_upgrade.py that throws away the actual error when logging12:42
geme_mgz, any idea why adding the repo failed ?12:42
mgzmy best guess is somehow the networking isn't up yet so it fails trying to talk to launchpad12:43
mgzbut could be anything, and after all the install works fine after that12:43
mgzone thing you could try is reproducing the error with `nova boot --user-data CLOUDCONFIGFILE`12:45
geme_mgz, when cloud-init runs can it access envars like HTTP_PROXY ?12:46
mgzwhere cloud config is just something like a file containing "#cloud-config\napt-sources:\n - source: ppa:juju/experimental" (with real newlines etc)12:47
mgzgeme_: set where? if you have some funky proxy setup for external net access, that is likely the issue12:47
geme_mgz, /etc/bash.bashrc12:48
mgzdoubt very much cloud-init will pick up that, except perhaps as a side-effect to some subcommands12:49
geme_mgz, Is there another way to make these proxy setting available to cloud-init ?12:51
mgzI'm not even sure that's sufficient, not everything respects HTTP_PROXY12:51
geme_mgz, so firewalls are a blocker then - sorry for the pun :)12:54
mgznot really, we've got a bunch of firewalled clouds that work fine12:54
mgzI don't think any try to do it using HTTP_PROXY though12:54
mgzwhich is an application level setting, if you're trying to inject that into your vms it doesn't seem a reliable way of doing things12:55
mgzyou need to configure openstack to understand your network setup12:55
geme_mgr, the proxy settings work in the shell12:57
mgzsure, because it's a shell12:57
mgzlots of things in a vm will not be spun up from bash12:57
mgzI think what you probably want is just a local apt proxy, but I'm still not sure how apt-add-reposistory interacts with that12:59
mgzyou might want to try asking in #juju how people have set up juju on openstack clouds without outgoing access to the wider internet13:00
mgzbecause a bunch of guys in there have done that13:00
geme_mgr, ok I'll ask. Thanks13:01
rogpeppedimitern: i realised that i'd missed most charms in my download, but rick_h in juju-gui pointed me to the charmworld api, so here's a program that downloads *all* the charms: http://paste.ubuntu.com/5992628/13:02
rogpeppedimitern: 663 successfully acquired at last count13:02
dimiternrogpeppe: nice13:02
rogpeppedimitern: and our relation regexp is still fine13:02
dimiternrogpeppe: great!13:02
dimiternrogpeppe: we should have some repo for such useful tools13:03
rogpeppedimitern: yeah, they might well be useful to others13:03
dimiternrogpeppe: so if you have a peer relation, are the remote and local units of it the same?13:05
rogpeppedimitern: no13:05
dimiternrogpeppe: why did you resolve all my comments on that document?13:06
rogpeppedimitern: i turned then all into notes13:07
rogpeppedimitern: which seemed a much more appropriate way of doing things13:07
rogpeppedimitern: (i didn't know about notes when i started adding comments)13:07
dimiternrogpeppe: ha! I didn't know there is such a feature13:07
rogpeppedimitern: thank rvba13:07
dimiternrvba: thanks :)13:07
dimiternrogpeppe: so I'm pondering how to get the remote unit from a relationunit13:08
dimiternrogpeppe: I can get the relation of the RU, call RelatedEndpoints on it, passing the local unit's service name13:08
dimiternrogpeppe: I'll a slice with length 1 (peer) or 2 (provider-requirer) with the endpoints13:09
dimiternrogpeppe: and I can get the remote service name from eps[0].ServiceName or eps[1].ServiceName respectively13:09
dimiternrogpeppe: but how to get which unit is on the other end?13:10
dimiternrogpeppe: /I'll a/I'll get a/13:10
rogpeppedimitern: an endpoint doesn't imply a unit13:11
dimiternrogpeppe: so there's no way to know which is the remote unit13:11
rogpeppedimitern: the client will need to name the unit, i think13:11
dimiternrogpeppe: ok, so ReadSettings cannot be made to enforce "use remote unit only"13:12
dimiternrogpeppe: in fact I can see in test that it gets called for the local unit as well13:12
rogpeppedimitern: well, there are many possible remote units13:12
dimiternrogpeppe: right..13:12
rogpeppedimitern: and we need to be able to read our own settings too13:12
dimiternrogpeppe: for that, you have another call13:13
dimiternrogpeppe: Settings()13:13
rogpeppedimitern: what's the difference between the two?13:13
dimiternrogpeppe: Settings() returns a mutable *Settings, whereas ReadSettings() returns a plain map[string]interface{}13:14
rogpeppedimitern: but they'll use the same underlying API call, right?13:14
dimiternrogpeppe: no13:18
dimiternrogpeppe: but perhaps they should actually13:18
rogpeppedimitern: ah, what's the difference?13:18
dimiternrogpeppe: ReadSettings only13:18
rogpeppedimitern: i think they're both doing the same thing13:18
rogpeppedimitern: the difference is only at the client side13:18
dimiternrogpeppe: and it to simulate Settings() you need to call it with "relation-x", "unit-x", "unit-x"13:19
dimiternrogpeppe: I have defined a RelationUnitPair with Relation, LocalUnit and RemoteUnit string13:19
dimiternrogpeppe: I can make RemoteUnit to be optional13:20
rogpeppedimitern: hmm, can't you just omit LocalUnit?13:20
rogpeppedimitern: because it's implied by the client13:21
dimiternrogpeppe: no, let's not do that13:21
dimiternrogpeppe: if we're going to start omitting stuff because it's implied by the authenticated entity, that's a whole new can of worms13:21
rogpeppedimitern: ok, fair enough13:22
dimiternrogpeppe: possibly making bulk calls a moot in general13:22
rogpeppedimitern: ahem, yes13:22
rogpeppedimitern: [don't get me started :-)]13:22
dimiternrogpeppe: so, until and if we decide to do that, I'll prefer to be explicit13:22
rogpeppedimitern: so LocalUnit must always be the authenticated unit, right?13:22
dimiternrogpeppe: yes13:22
rogpeppedimitern: so i think there's no need to make RemoteUnit optional13:23
rogpeppedimitern: if you want to get settings of the remote unit, just have RemoteUnit==LocalUnit13:23
dimiternrogpeppe: so pass both and make them the same to request local settings13:23
dimiternrogpeppe: ok13:23
dimiternrogpeppe: no, it's exactly the opposite :)13:23
rogpeppedimitern: then RemoteUnit is always the tag of the unit you're asking for settings of13:23
dimiternrogpeppe: Local!=Remote => remote settings13:23
rogpeppedimitern: ha, yes, typo13:24
rogpeppedimitern: if you want to get settings of the *local* unit... !13:24
dimiternrogpeppe: ok then, almost done - will propose soon13:24
rogpeppedimitern: cool13:24
dimiternrogpeppe: remind me again why you removed the unitTagToName conversion from names?13:28
rogpeppedimitern: you've got ParseTag now13:28
dimiternrogpeppe: ah, right13:28
rogpeppedimitern: when you've a moment, try running "go get launchpad.net/juju-utils/cmd/getallcharms"13:38
rogpeppedimitern: there's also launchpad.net/juju-utils/cmd/charmmeta13:39
geme_mgz, added repo to the image. Now bootstraps successfully and juju status respond. Likely the problem will come back and bite me.13:39
dimiternrogpeppe: done both13:39
rogpeppedimitern: you could try and see if it works13:40
rogpeppedimitern: e.g. getallcharms ~/allcharms13:40
dimiternrogpeppe: trying now13:40
rogpeppedimitern: it should fetch all the charms in the charm store13:40
dimiternrogpeppe: is there a -v option?13:40
dimiternrogpeppe: ah, it dumps them13:40
rogpeppedimitern: yeah. it's actually verbose by default13:41
dimiternrogpeppe: for some it reports 2013/08/16 15:40:58 get "cs:~philipballew/precise/dyndns-0" failed: charm "noip2" relation "dynamic-ip-reporting" using a reserved interface: "juju-info"13:41
rogpeppedimitern: yup, that's the most common issue13:41
dimiternrogpeppe: done, 361M fetched13:42
rogpeppedimitern: cool13:42
dimiternrogpeppe: and charmmeta ?13:42
dimiternrogpeppe: it's not recursive13:43
rogpeppedimitern: now you can run charmmeta over all of them by doing something like: charmmeta sometemplatetext $(cat $HOME/allcharms/urls.txt)13:43
rogpeppedimitern: no - it probably should recurse looking for metadata.yaml files13:44
rogpeppedimitern: but i've spent too much time on it already :-)13:45
dimiternrogpeppe: np, with some tweaking it works13:45
rogpeppedimitern: what tweaking?13:45
dimiternrogpeppe: charmmeta '..template..' `cat ~/allcharms/urls.txt` fails13:46
dimiternrogpeppe: it reports Dir==nil on each line13:46
rogpeppedimitern: ah!13:47
rogpeppedimitern: that's because you need to be inside the allcharms directory13:47
dimiternrogpeppe: yeah, I figured :)13:47
dimiternman.. testing Enter and LeaveScope is a bitch13:49
dimiternI have to use a scope watcher..13:49
rogpeppedimitern: charmmeta is now recursive. couldn't quite resist doing it now :-)14:04
dimiternrogpeppe: cool, will test it14:07
* rogpeppe must get some lunch now14:11
=== tasdomas is now known as tasdomas_afk
rogpeppetrivial review, anyone? https://codereview.appspot.com/1305304315:07
rogpeppejust some package renaming, mechanical changes15:08
natefinchrogpeppe: I can review it15:15
rogpeppenatefinch: thanks15:15
natefinchrogpeppe: reviewed. LGTM, bonus points for fixing a few of the import sorts15:23
rogpeppenatefinch: good catch15:23
rogpeppedimitern, mgz, rvba, jtv, fwereade: another review appreciated please. trying to avoid a prereq. https://codereview.appspot.com/1305304315:30
dimiternrogpeppe: looking15:33
rogpeppedimitern: ta15:33
rogpeppedimitern: i okayed this with fwereade previously, BTW15:33
dimiternrogpeppe: while I'm at it, would you look at https://codereview.appspot.com/1305504315:34
rogpeppedimitern: looking15:34
dimiternrogpeppe: thanks15:36
dimiternrogpeppe: didn't we discuss having the providers at top-level?15:36
rogpeppedimitern: they're very much to do with environs15:36
rogpeppedimitern: (they implement an interface defined in environs)15:36
rogpeppedimitern: so i strongly feel they below below environs15:37
rogpeppedimitern: (as does instance, but that's another story)15:37
dimiternrogpeppe: that shouldn't stops us - there are cases where other packages implement interfaces defined outside their parent package15:37
rogpeppedimitern: yes, but really environs is all about providers15:37
rogpeppedimitern: hmm, well, i can see your p.o.v. too15:38
dimiternrogpeppe: providers, like charms are things that need an environment15:38
rogpeppedimitern: not really: providers *provide* an environment15:39
dimiternrogpeppe: but really the environment needs both of them15:39
rogpeppedimitern: well, they provide an Environ anyway15:39
dimiternrogpeppe: the environment is much more that what a provider provides15:39
dimiternrogpeppe: it provides means to access the environment, but not the only means15:39
rogpeppedimitern: a provider provides an Environ15:40
dimiternrogpeppe: state and API are other means to access it15:40
rogpeppedimitern: and that's what environs is all about15:40
dimiternrogpeppe: well, Environ is hardly the best name for it15:40
rogpeppedimitern: state and API don't really have anything to do with Environ15:40
rogpeppedimitern: that may be true15:40
dimiternrogpeppe: i think we're conflating the Environ type and what a juju environment is all about15:41
dimiternrogpeppe: the Environ type is *not* a juju environment15:41
rogpeppedimitern: i didn't say it was15:41
rogpeppedimitern: well,15:41
rogpeppedimitern: it depends what you mean by a juju environment15:41
dimiternrogpeppe: I mean both local and remote stuff15:42
rogpeppedimitern: but regardless, the provider types are there entirely to implement the interface defined in environs/interface.go15:42
dimiternrogpeppe: settings, instances, cloud account info15:42
rogpeppedimitern: they aren't accessed in any way accept through environs15:42
rogpeppedimitern: so i think it's reasonable to put them under that directory15:43
dimiternrogpeppe: they are - through the CLI and the API15:43
rogpeppedimitern: not really. whenever the CLI gets an Environ, it gets it via the environs package15:43
dimiternrogpeppe: should we put the API in environs as well, because all it does is to provide access to a running environment's parts?15:43
rogpeppedimitern: no, an Environ (whatever it should really be called) is all about encapsulating provider-specific functionality15:44
dimiternrogpeppe: I really liked the way pyjuju has providers at top level15:44
rogpeppes/whatever/or whatever/15:44
dimiternrogpeppe: and the argument that providers need to implement an interface in environs/interface.go is not a strong point to keep them together IMO15:45
dimiternrogpeppe: we have plenty of cases where that's not true15:46
rogpeppedimitern: if they provided independent functionality too, i might agree15:46
rogpeppedimitern: but given that nothing else in the system imports them directly (except for the side effect of having them there, and excepting dummy which is special), i think it's reasonable to hide them under environs15:47
dimiternrogpeppe: how about the null provider?15:47
dimiternrogpeppe: it's not a complete provider - also possibly the ssh one15:48
rogpeppedimitern: i don't know what the null provider is. have we got one of those?15:48
dimiternrogpeppe: we will soon15:48
dimiternrogpeppe: read the specs15:48
dimiternrogpeppe: it's an example of a "partial" provider15:49
dimiternrogpeppe: you cannot start or stop instances for example15:49
dimiternrogpeppe: or xenv rels?15:49
rogpeppedimitern: it will still need to implement all the methods defined in environs.EnvironProvider15:49
rogpeppedimitern: even if it returns errors for some of them15:49
dimiternrogpeppe: I'm saying this might change15:50
rogpeppedimitern: i'm not sure it needs to15:50
dimiternrogpeppe: we might need to separate that huge interface into smaller ones15:50
rogpeppedimitern: and we can change things again when that happens15:50
rogpeppedimitern: i plan to do just that15:50
dimiternrogpeppe: well..15:50
rogpeppedimitern: but i'm still happy to have them all under environs15:51
dimiternrogpeppe: ok, at least havingthem in environs/provider/ will clean up some of the mess already in there15:51
dimiternrogpeppe: the same should apply to cloudinit imo15:51
rogpeppedimitern: where should environs/cloudinit go?15:51
dimiternrogpeppe: in cloudinit/15:51
rogpeppedimitern: cloudinit/cloudinit ?15:52
rogpeppedimitern: (there's already a juju-core/cloudinit package)15:52
dimiternrogpeppe: I know15:52
dimiternrogpeppe: why shouldn't it be in the same top-level package?15:52
dimiternrogpeppe: why the separation?15:52
rogpeppedimitern: because the top level package is entirely juju-agnostic15:53
rogpeppedimitern: whereas environs/cloudinit is intimately bound up with juju environment-related stuff15:53
rogpeppedimitern: and that's kinda where my reasoning for when we should have a top level package or namespace comes from - it should be largely independent functionality.15:54
dimiternrogpeppe: anyway, that's entirely another topic in its own right15:54
rogpeppedimitern: the cloudinit package works well as something standalone. environs/cloudinit builds neatly on top of it.15:55
dimiternrogpeppe: if it's independent it shouldn't be in juju-core - it should be an outside package15:55
rogpeppedimitern: perhaps. but if we don't care about other people using them, it's more convenient to keep it in juju-core15:55
rogpeppedimitern: we can still have decent modularity, even inside juju-core15:56
dimiternrogpeppe: if it's useful independently, it shouldn't be inside15:56
rogpeppedimitern: there are lots of pieces that are useful independently. having them outside is a burden we don't want to have to bear for all of them15:56
rogpeppedimitern: schema and rpc are two examples15:57
rogpeppedimitern: anyway, anyone outside can still use these things15:57
rogpeppedimitern: they don't need to be in an independent package to enable external reuse15:57
dimiternrogpeppe: I don't quite agree the burden is that big15:58
dimiternrogpeppe: most of this things are stable and change rarely15:59
rogpeppedimitern: i don't think there's that much in the way of advantage from having them in separate projects15:59
dimiternrogpeppe: actually that could be a reason to move it out15:59
dimiternrogpeppe: of course there is - smaller code base, easier to maintain15:59
rogpeppedimitern: i don't think the maintenance burden is any smaller if the code is separated across several projects16:00
rogpeppedimitern: the opposite if anything16:00
dimiternrogpeppe: there's only a burden if we have to update them often - the same thing as with gwacl, goose, etc.16:00
rogpeppedimitern: if we don't need to update them, where's the burden from having them in the same code base?16:01
rogpeppedimitern: i think it's great to build a project from many small indpendent parts16:01
rogpeppedimitern: and if those parts were principally built for the main project, i don't really see there's an advantage to moving them out16:02
rogpeppedimitern: the main advantage of doing that is if we want to promote external users of those packages16:02
dimiternrogpeppe: it's not a burden as such to have them in the same codebase, it just inflates it, and if they rarely change, it's actually better and cleaner to have them outside16:03
rogpeppedimitern: i guess i don't see that. the more external dependencies, the more hassle.16:03
rogpeppedimitern: otherwise we'd have one project for each package16:04
dimiternrogpeppe: what's the hassle exactly?16:05
rogpeppedimitern: moving the code base to different versions doesn't automatically update the dependencies16:05
rogpeppedimitern: i can see the history of those dependencies in with the main log16:06
rogpeppedimitern: if they're inside the code base16:06
dimiternrogpeppe: aren't we moving towards handling dependencies better in general?16:06
rogpeppedimitern: yeah, but it's still not cost-free16:06
dimiternrogpeppe: it depends on how easy we make it16:07
dimiternrogpeppe: nothing is cost free, there are hidden costs you have to consider16:08
rogpeppedimitern: back to the environs/provider thing: for me, it's about strict encapsulation boundaries. the environs package should entirely encapsulate the different providers.16:08
rogpeppedimitern: hidden costs like?16:08
dimiternrogpeppe: reviewed16:09
rogpeppedimitern: i don't want to do any import renaming in that branch if that's ok. i can go through in another branch doing all the gocheck renames if you'd like16:10
dimiternrogpeppe: like having a bunch of code which is not directly juju-related, only slightly and could be reused by external projects16:11
rogpeppedimitern: external projects can still reuse that code16:11
dimiternrogpeppe: Ok, at least fix the imports separation then - they were just a few16:12
rogpeppedimitern: (and does - for instance that charmmeta command)16:12
rogpeppedimitern: will do, thanks16:12
dimiternrogpeppe: i don't want to argue anymore about this - it deserves a separate discussion in good time :)16:13
rogpeppedimitern: indeed :-)16:13
natefinchdimitern, rogpeppe:  FWIW I agree with both of you... both ways have advantages and disadvantages. It's a tale as old as time (or at least as old as modern programming)16:13
dimiternnatefinch: nah.. c'mon you can't agree like that :)16:15
natefinchdimitern: what, I have to take a side?  :)16:16
dimiternnatefinch: hehe16:16
dimiternnatefinch: you can have a look at this perhaps? https://codereview.appspot.com/13055043/16:16
natefinchdimitern: sure16:18
dimiternnatefinch: ta16:19
natefinchdimitern: just curious, why do we do "type RelationUnits struct { RelationUnits []RelationUnit}"  rather than "type RelationUnits []RelationUnit" ?16:23
dimiternnatefinch: because the rpc layer of the API needs a struct as args and results16:23
natefinchdimitern: ahh, ok16:24
dimiternnatefinch: take a look at doc/api.txt and rpc/server.go -> Serve()'s doc comment you're interested in the internals16:25
dimiternfwereade_: hey16:25
dimiternfwereade_: just in time for a review? :)16:25
dimiternnatefinch: thanks16:51
dimiternnatefinch: btw - I'd like to leave the checkers.IsTrue etc. for a follow-up, if you don't mind. The diff is already big enough16:52
dimiternrogpeppe: does it look roughly ok?16:56
rogpeppedimitern: i'm working on doing all the gc.etc stuff in about 4 giant branches16:56
rogpeppedimitern: i think i can do most of the changes automatically16:57
dimiternrogpeppe: good to hear16:57
dimiternrogpeppe: but please don't forget my branch as well ;)16:57
rogpeppedimitern: i'm looking now16:58
dimiternrogpeppe: cheers16:59
natefinchrogpeppe: I was looking at how to do the . to gc change automatically... did you find a good way to do it?17:03
rogpeppenatefinch: i've got a command that may help - we'll see if it's up to the task17:03
rogpeppenatefinch: it's pretty much a failed experiment, but still sometimes useful17:04
natefinchrogpeppe: yeah, I looked around for something that might already do it, gofix or something, but nothing seemed to be able to do it, so I was looking into writting a command to do it by parsing the AST... hopefully yours will work so I don't have to do that :)17:04
rogpeppenatefinch:code.google.com/p/rog-go/exp/cmd/gosym17:04
rogpeppenatefinch: gofmt isn't far off being able to do it17:05
natefinchrogpeppe: yeah, I looked at gofmt too... wasn't sure how to get it to figure out what is getting imported by . and fix it automatically.... at least in the general case17:06
rogpeppenatefinch: it can't do that17:06
rogpeppenatefinch: it needs to resolve type symbols17:06
rogpeppenatefinch: gosym resolves symbols but it doesn't cope with import to . well17:07
natefinchrogpeppe: I'm honestly surprised import . even exists in Go.  Seems like the kind of "almost always a bad idea" thing that it would not support17:09
rogpeppenatefinch: it's only there for a particular edge case17:09
rogpeppenatefinch: but it's been abused17:09
rogpeppedimitern: can settings attributes be deleted?17:14
dimiternrogpeppe: they are replaced17:15
dimiternrogpeppe: so yeah17:15
rogpeppedimitern: hmm, it looks like relation-set calls settings.Delete17:15
dimiternrogpeppe: perhaps an additional test is needed17:15
rogpeppedimitern: but it looks as your API doesn't cater for deletions17:16
dimiternrogpeppe: settings.Delete is only local17:16
rogpeppedimitern: it's possible that's not a problem though17:16
dimiternrogpeppe: any changes are always written with Settings.Write()17:16
rogpeppedimitern: but if you've called Delete, Settings.Write will actually delete the attribute17:17
rogpeppedimitern: it doesn't just overwrite it with nil17:17
dimiternrogpeppe: the settings are one blob, right?17:18
rogpeppedimitern: no17:18
rogpeppedimitern: the settings are held as mongo fields17:18
rogpeppedimitern: each settings gets its own field17:18
rogpeppes/settings/setting/17:18
rogpeppedimitern: look in state/settings.go17:18
dimiternrogpeppe: so what happens when you overwrite it with some different map?17:18
rogpeppedimitern: it changes only the ones that have locally changed since you last read the settings17:19
rogpeppedimitern: it unsets the ones that have been deleted and sets the others17:19
rogpeppedimitern: it might be reasonable to say that setting a value to nil will be treated as a deletion17:20
dimiternrogpeppe: ok, will add more tests to make sure what I can read from the unit after calling WriteSettings is exactly as passed in the args17:21
rogpeppedimitern: how will attributes get deleted?17:21
dimiternrogpeppe: by calling Update before Write?17:21
rogpeppedimitern: Update never deletes an attribute17:21
dimiternrogpeppe: so you're saying the operation has to be more sophisticated17:22
rogpeppedimitern: i think so... assuming we care about deleting attributes17:23
dimiternrogpeppe: reading old settings, finding what to delete, updating the rest, finally writing the result17:23
rogpeppedimitern: no17:23
dimiternrogpeppe: no?17:23
rogpeppedimitern: the API call has to be able to specify which settings are to be deleted17:23
dimiternrogpeppe: delete just does delete(c.core, key)17:24
dimiternrogpeppe: it doesn't seem it keeps the deleted ones separately17:24
rogpeppedimitern: it infers which ones are deleted by looking at the difference between c.core and c.disk17:24
dimiternrogpeppe: assuming we start with an empty map, update with the new settings, then write should take care of deletions as well17:24
rogpeppedimitern: what happens if we do: Update({"x": "y"}) then Update({}) ?17:25
dimiternrogpeppe: will delete everything17:25
rogpeppedimitern: nope17:25
rogpeppedimitern: "x" will still be around17:25
dimiternrogpeppe: no, I mean we can't do that really17:25
dimiternrogpeppe: Update is client-side only17:26
dimiternrogpeppe: on the API level we have read and write only17:26
rogpeppedimitern: it would be possible to make Update overwrite all attributes17:26
rogpeppedimitern: but i don't think that's a great idea17:26
dimiternrogpeppe: how?17:27
rogpeppedimitern: because it means potentially quite a bit more network traffic17:27
dimiternrogpeppe: sorry, I don't get you17:27
dimiternrogpeppe: we have old settings, we want to write new ones we got over the wire17:27
rogpeppedimitern: if a hook just does a single "relation-set x=y", we don't really want to send all the other settings too17:27
dimiternrogpeppe: calling Read() will reset the disk cache, then we reset all core values, update the new ones, then write17:28
rogpeppedimitern: are you talking client- or server-side here?17:28
dimiternrogpeppe: server-side17:28
dimiternrogpeppe: client-side we implement a Settings proxy object with a subset of the interface that state.Settings has, but only Write calls the API17:29
dimiternrogpeppe: the overhead is not significant17:29
rogpeppedimitern: if we replace all core values, the client must send all those values up with the Write call17:29
dimiternrogpeppe: yes it will17:29
dimiternrogpeppe: the client calls Write eventually17:29
dimiternrogpeppe: in context, if I'm not mistaken, after the hook is comitted17:30
dimiterncommitted17:30
dimiternrogpeppe: yep, context.go:29017:30
rogpeppedimitern: are you happy that at the end of the hook, all settings will be sent across the network, even if they have not changed?17:30
dimiternrogpeppe: I see no problem with that17:30
dimiternrogpeppe: the settings are usually just a few17:31
rogpeppedimitern: i don't know - have you looked at how charms use settings?17:31
dimiternrogpeppe: a few yes17:31
rogpeppedimitern: i think it's quite possible that people have some large values in there sometimes17:31
dimiternrogpeppe: haven't look through all of them17:31
rogpeppedimitern: we're not talking about config settings17:31
dimiternrogpeppe: can we check that reliably?17:32
dimiternrogpeppe: find all relation-set calls in all charms?17:32
rogpeppedimitern: no - i just think it's not hard to be a little more efficient17:32
dimiternrogpeppe: like how?17:32
dimiternrogpeppe: have UpdateSettings and DeleteSettings calls?17:32
dimiternrogpeppe: pass every client-side call over the wire?17:33
rogpeppedimitern: we could treat a nil value as a delete17:33
rogpeppedimitern: so to delete an attribute you'd do: WriteSettings({"x": nil}) for example17:33
dimiternrogpeppe: deletes are not a problem17:33
dimiternrogpeppe: you're talking about something different17:33
dimiternrogpeppe: having incremental updates17:34
rogpeppedimitern: afaics, deletes are the only problem with the current scheme17:34
rogpeppedimitern: the current scheme will work fine to do incremental updates17:34
rogpeppedimitern: the only exception being that you won't be able to delete an attribute17:34
dimiternrogpeppe: the current scheme will change as described and deletes won't be a problem anymore - it'll overwrite all stuff on write17:34
dimiternrogpeppe: not really17:35
dimiternrogpeppe: we're removed from the source when using the API17:35
dimiternrogpeppe: we can't rely on Update to do things smartly17:35
dimiternrogpeppe: we read the settings every time when we're about to write them17:35
dimiternrogpeppe: so there's no cache, etc.17:36
rogpeppedimitern: i thought the idea was to replicate some similar Settings logic client side17:36
dimiternrogpeppe: yeah, except for Write17:36
dimiternrogpeppe: but Write will still overwrite what's currently in state17:36
rogpeppedimitern: so that the client would read settings, make some modifications, then call Write, which could intelligently decide which have changed and issue an appropriate Update API call17:36
dimiternrogpeppe: I'm not keen on the idea of having an Update API call17:37
rogpeppedimitern: why not?17:37
dimiternrogpeppe: it seems too much complexity for very marginal gain17:37
rogpeppedimitern: in that case, there's no point in duplicating any of the Settings logic in the client side.17:38
rogpeppedimitern: the uniter may as well just use map[string]interface{} directly17:38
dimiternrogpeppe: it being "in the odd case some charm writes huge settings keys once and changes a few smaller ones often"17:38
dimiternrogpeppe: well, it doesn't and changing the uniter is not necessary17:38
dimiternrogpeppe: the client-side will replicate the same logic with a proxy Settings17:39
dimiternrogpeppe: but on Write it'll overwrite current settings17:39
dimiternrogpeppe: and it will still work the same17:39
dimiternrogpeppe: update and delete will operate on the proxy object's internal map17:39
dimiternrogpeppe: write will send the final, merged map for saving17:39
rogpeppedimitern: you'd only need one map, of course.17:40
dimiternrogpeppe: yeah17:40
dimiternrogpeppe: I can add a TODO in WriteSettings saying something like "if this proves to be inefficient we can change it to allow incremental updates" ?17:41
rogpeppedimitern: how are you going to reset all attributes, BTW?17:42
dimiternrogpeppe: in fact, having huge values in settings keys is a possible DoS attack on mongo from a malicious charm17:42
dimiternrogpeppe: get the old ones, delete everything, write, update, write again is the easiest way that comes to mind17:43
dimiternrogpeppe: but perhaps there's a more efficient way, have to experiment a bit, to do it with a single write17:43
rogpeppedimitern: i'm not sure there's a "delete everything" mongo operation17:43
dimiternrogpeppe: there is $unset deletions17:44
dimiternrogpeppe: that's what Write does17:44
rogpeppedimitern: yes, but you have to know what attributes to unset17:44
rogpeppedimitern: and the way you're using Settings, unset will never happen17:45
dimiternrogpeppe: all of them, which do not conflict with the new ones, which are simply updated17:45
rogpeppedimitern: how do you know the "all"?17:45
dimiternrogpeppe: yes, we already discussed that, I change what's being done on WriteSettings17:45
dimiternrogpeppe: there's Keys()17:46
dimiternrogpeppe: or, perhaps simpler - get and delete each key not in the new map17:46
dimiternrogpeppe: just delete actually should do it17:46
rogpeppedimitern: ISTM like the state.Settings object is actually getting in the way here.17:47
dimiternrogpeppe: after doing Read to populate the disk cache17:47
dimiternrogpeppe: how so?17:47
rogpeppedimitern: because you'll be duplicating the same kind of logic that's already inside Settings17:47
dimiternrogpeppe: not much - just a for loop for deletions, a read before it, and update + write after it17:48
rogpeppedimitern: part of the reason i'm slightly concerned here is that i suspect that these settings writes may be a good proportion of the ongoing mongo traffic in a large juju installation17:48
dimiternrogpeppe: yeah, and how is my approach different from what's already happening?17:49
dimiternrogpeppe: we always read them to create a settings object, do some ops on it, and call write finally - only the first and last operations are actually mongo ops17:50
rogpeppedimitern: currently for each hook execution, we only have two mongo ops: read then write17:50
rogpeppedimitern: we're going to change that so that it reads twice17:50
rogpeppedimitern: and also currently, we read the settings, but we only write the data for the ones that have changed17:51
dimiternrogpeppe: not really, we can change the settings object to provide ClearCache method17:51
rogpeppedimitern: how will that work?17:51
dimiternrogpeppe: that way we'll still have 1 read and 1 write17:51
rogpeppedimitern: i don't know how if there's a mongo operation to delete all attributes on a doc without knowing what those attributes are.17:52
dimiternrogpeppe: it doesn't matter how many keys we set or unset - it's still a single update operation17:52
dimiternrogpeppe: I'm not talking about a mongo operation17:52
dimiternrogpeppe: I'm talking about ClearCache method which clears the settings object's internal disk cache17:52
dimiternrogpeppe: the same one write uses to determine which keys to unset17:53
rogpeppedimitern: uniter.go:725  reads all the settings; uniter.go:728 writes them17:53
rogpeppedimitern: every hook execution will call ReadSettings (which reads all the settings), then WriteSettings (which reads all the settings then writes them)17:53
dimiternrogpeppe: can we please stop discussing what's there now and focus on what we want to have there?17:54
dimiternrogpeppe: that's what I'm trying to explain17:54
rogpeppedimitern: ok, so i think we still want to have ReadSettings followed by WriteSettings, right?17:54
dimiternrogpeppe: yes17:54
dimiternrogpeppe: it's the same as now17:54
rogpeppedimitern: so the question is: how does WriteSettings delete any attributes which aren't in the map we're writing?17:54
dimiternrogpeppe: RU.Settings() does readSettings, Settings.Write() does the write17:55
rogpeppedimitern: right - so we'll still have exactly the situation i described above, no?17:55
dimiternrogpeppe: by deleting them from the map, unless they are to be overwritten by keys in the new map17:55
rogpeppedimitern: i.e. we'll read all the settings twice, then write them17:56
dimiternrogpeppe: ah, right, but in 2 separate API calls17:56
rogpeppedimitern: yes17:56
rogpeppedimitern: but the increase in mongo traffic is real17:57
dimiternrogpeppe: read does read, write does read+delete+update+write17:57
dimiternrogpeppe: how can you measure that?17:57
rogpeppedimitern: write *should* just do a single mongo update transaction, i think17:57
rogpeppedimitern: and i don't think it's at all hard to arrange that17:57
dimiternrogpeppe: we can't avoid the read in WriteSettings17:58
rogpeppedimitern: yeah, i think we can17:58
dimiternrogpeppe: we don't have the orinal settings object around anymore17:58
rogpeppedimitern: we'll just have to bypass the Settings object entirely.17:58
rogpeppedimitern: it's not really appropriate for the server side17:59
rogpeppedimitern: however....17:59
dimiternrogpeppe: ah, so you're saying implment state.WriteSettings that does all that in one go?17:59
rogpeppedimitern: yeah. or probably RU.WriteSettings17:59
dimiternrogpeppe: ok, that sounds reasonable17:59
rogpeppedimitern: however... perhaps we could leave this as a TODO18:00
dimiternrogpeppe: and how will that work internally, without knowing what keys are already there?18:00
rogpeppedimitern: we treat nil elements in the map passed to WriteSettings as deletions18:00
rogpeppedimitern: the client side keeps track of deletions and passes them through as nils18:01
dimiternrogpeppe: that seems worse traffic-wise18:01
rogpeppedimitern: only if deletions are common18:01
dimiternrogpeppe: now, instead of sending only stuff we actually want to store, we'll send also deleted things18:02
rogpeppedimitern: we'll be sending deltas18:02
rogpeppedimitern: if there are more than a few attributes that aren't changed, then it'll definitely be a win18:02
dimiternrogpeppe: yeah, that's one of those questions with no easy answers without having to go through every charm hook18:02
rogpeppedimitern: yeah18:02
rogpeppedimitern: it would be great to have some operational data to inspect18:03
rogpeppedimitern: i really have to go, i'm afraid18:03
dimiternrogpeppe: ok, so: 1) treat key->nil as deletions, 2) update the rest18:03
rogpeppedimitern: for the time being, i think you could leave it as it is18:03
dimiternrogpeppe: 3) add a todo to possibly replace all that with a RU.WriteSettings call18:03
rogpeppedimitern: we won't be able to delete anything, but i don't think that's a big problem for the time being18:04
rogpeppedimitern: actually, yes, that will work better18:04
dimiternrogpeppe: ok, let's continue on monday then18:04
rogpeppedimitern: then deletions will actually work, and we can be more efficient later18:04
rogpeppedimitern: cool, thanks for going along with me18:04
dimiternrogpeppe: no worries, it was useful18:05
dimiternrogpeppe: have a good weekend! :)18:05
rogpeppedimitern: i will - going to a folk festival, yay!18:05
rogpeppedimitern: and you18:05
rogpeppedimitern: ttfn18:05
rogpeppeg'night all18:06
dimiternyay :)18:06
dimiternfiddles then18:06
rogpeppeoooh yes18:06
* dimitern @ eod as well18:10
dimiternsee y'all on monday!18:11

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