[02:24] o/ [05:16] Question: When using the test harness, is there anything special we need to do in our unit test to make this line work in the SUT's code? `self.framework.model.resources.fetch('grafana-image')` [07:07] MarkMaglana, I believe resource support is something that needs to be implemented [07:08] MarkMaglana, I would expect to have some sort of setup on the Harness, where you tell it what paths you should return for a resource request [07:08] MarkMaglana, issue #262 [07:09] * jam heads to take the coffee machine to the shop, critical infrastructure :) [07:28] jam: thanks for that! [07:29] and black coffee for me today, please! [08:09] another question. what other steps do i need to perform prior to exposing a k8s workload via `juju expose ` [08:09] morning all [08:11] top of the mornin' to ya Chipaca! [08:11] bottom of the afternoon for me though [08:12] *my* morning, all [08:12] :-p [08:32] MarkMaglana, you shouldn't need to do much as a user, you can include "expose" as part of a bundle [08:32] as a charm developer, you need to call 'open-port' in order to tell Juju what to expose. [08:33] Chipaca, good morning [08:33] jam: actually i discovered just now that i don't even need to run `juju expose`. I can access the app via its IP directly. but that's only if i access it from within the host. (i'm using microk8s) [08:42] jam: how're things? [08:43] Chipaca, well, coffee machine broke.. so I took it into the shop, but otherwise things are going ok [08:43] /o\ [08:43] jam: i too have coffee woes … my postie has gone missing, with now two coffee deliveries missed (and some masks my mum made) [08:44] i'm now down to instant [08:44] Chipaca, ouch! my deliveries have been regular, which is good. And we have a backup nespresso machine that my wife usually uses for decaf [08:45] Chipaca, but if you have instant, you have Dalgona, right? [08:45] on the one hand, yes [08:46] cold brew ftw! [08:46] on the other hand, that thing takes ages to make and dirties a lot more than just a coffee [08:46] one of the things i like about my aeropress is the minimal mess [08:46] ¯\_(ツ)_/¯ [08:47] pretty inexpensive to get a replacement, but you might need to go out of the house for that [08:47] jam: still out of coffee for it tho [08:48] :) [08:48] sometimes you can find places that sell things for money, which sometimes includes coffee :) [08:48] jam: this is true, and i might resort to that if i tire of my instant [08:48] the instant is only ever meant as an emergency ration kind of thing :) [08:49] my delivered coffee is so much better than what i can get in the supermarket, the few times i have bought coffee there it ends up going off [08:49] ANYway [08:50] jam: is my approach on #284, wrt initial values for _status, reasonable? ie having unkown for app and maintenance for unit? [08:50] jam: (and if maintenance for unit, is there any particular message i should set on it?) [08:50] i tried seeing what message juju set but it was beyond my ken still [08:51] Chipaca, works for me [08:51] No message on the unit [08:51] which is why you couldn't find it :) [08:51] Chipaca: aeropress is awesome. And I'm still wondering why I haven't bought one. Something is wrong with me. [08:52] MarkMaglana: because you're at a local comfort extreme and getting out of it requires work? [08:53] Chipaca: mystery solved! [09:03] boo, 3.5 doesn't like foo: bar = 'baz' [09:16] Chipaca,even if it is "foo: str = 'baz' " ? [09:17] jam: yeah, it's a 3.6ism [09:17] for 3.5 we're stuck with the entirely unsatisfying # type: str [09:17] Chipaca, I think I still need your review of couldn't find it :) [09:17] Chipaca: aeropre [09:18] sorry bad paste [09:18] https://github.com/canonical/operator/pull/279 [09:18] Chipaca, I thought I had done that syntax, but it was probably '=None' [09:18] jam: on it already :) [09:19] jam: i could use one on #190 also [09:26] Chipaca, approved #190, I'd like to see us fix the bits that don't get PYTHONPATH set correctly, etc. but nothing in that is wrong, just doesn't quite 'juju deploy .' with the actual text that was written [09:28] jam: yep, I'm going to be pushing for us to have at least that bit of charmcraft build done before the next biweekly email :) [09:28] jam: which reminds me, did you get to give that a read? [09:30] Chipaca, yeah. it looks good to me, depends a bit on who the audience is. Is it just a Discourse "here's what we're doing" sort of thing? [09:30] jam: and to our mailing list (!) [09:31] Chipaca, isn't Discourse the New(tm) mailing list? [09:31] jam: for this sort of thing, i have 0 problem in posting it to the old *and* the new [09:31] :) [09:51] Chipaca, I just didn't know of an external mailing list that people wanting announcement style messages would be signed up to [09:52] jam: there's probably at most one or two people on the list that aren't watching discourse, but i care for them :) [11:16] Muy buenos días a todos! [11:31] * Chipaca reading https://www.conventionalcommits.org/en/v1.0.0/ and going "hmm" a lot [11:32] facubatista: how're you doing? [11:34] Hey! qq [11:35] Do you know if an async action will work in the operator framework? [11:35] davigar15: what's an async action in this context? [11:35] actions work :) [11:35] but i didn't know juju had 'async' actions [11:36] ``` [11:36] async def get_chat_id(name): [11:36] await asyncio.sleep(3) [11:36] return "chat-%s" % name [11:36] ``` [11:36] Coroutine I mean [11:36] With asyncio [11:38] Chipaca: So instead of having `def on_whatever_action`, we'd have `async def on_whatever_action` [11:38] davigar15: and what would that do? [11:40] Well, I don't know about the internals of it, but basically when you put async in a function definition, that function is a coroutine that can `await` to other functions. Is the way to implement asynchronous functions in python [11:42] davigar15: yes, I know. I'm asking what that would do for the charm :) [11:42] davigar15: that is: what is the advantage of it for you, the charm writer [11:43] currently we don't support this, fwiw [11:43] In my usecase, I have a charm that SSH to a machine using paramiko. I'd like to remove that dependency, and implement the ssh function this way: https://github.com/juju/python-libjuju/pull/393/commits/7ceb7561b6eb3b070868eb28c4ad47791ae1aa7c [11:44] For that I need to `await ssh(cmd)`, and we can only await in coroutines [11:44] davigar15: there's nothing stopping you doing that in the handler [11:44] davigar15: you don't need the event handler to be async for that [11:45] that is, you can write pretty much the same 'async def ssh(...)' and then await ssh() in your _on_foo event handler and it'd work [11:46] import asyncio [11:46] await asyncio.sleep(4) [11:47] ^ If I put that in an event handler, it says: undefined variable: await [11:47] mmm... [11:47] warning that disappears when I put `async` in the definition [11:48] davigar15, let me try something [11:48] 😉 [11:52] ah, i forgot the await-only-in-async [11:53] davigar15: from python 3.7, that'd be asyncio.run(asyncio.sleep(4)) [11:54] davigar15: before 3.7 it's asyncio.get_event_loop().run_until_complete(asyncio.sleep(4)) [11:54] davigar15, I just tried this as a script, but you can do the parallelism: https://paste.ubuntu.com/p/FBTdb5bVV9/ [11:54] facubatista: poncho! :) [11:54] davigar15, you'd need to start the event loop on each call, though, and wait for everything to complete before ending [11:54] davigar15, and finally, take into account that any call *back to the framework* would be blocking [11:55] Chipaca, :) [11:55] What do you mean with "would be blacking"? [11:56] davigar15, "blocking", not blacking, as "it will not be async" [11:57] * facubatista brb [11:59] sorry for the typo. Okay, understood [11:59] Thanks :) [11:59] davigar15: sorry if you already answered this, but what is the advantage to you to having your ssh function be async? [12:00] * facubatista is back [12:00] Basically I did that in the SSHProvisioner in libjuju, and was to reuse that function here. [12:00] I can simply execute subprocess.check_call() [12:01] And will be the same [12:02] davigar15, but it is an external process the one you're calling? [12:02] *is it [12:03] I'm doing `ssh @[...] cmd` in the charm [12:04] The process is executed in the charm, but it basically does ssh to a machine to execute whatever function [12:04] It is what we called in OSM: proxy charm. [12:04] davigar15, my point is that the process is NOT executed in the charm, it's a *sub*process [12:04] davigar15, so, you would need to wait for it from the charm [12:04] yep [12:04] exactly [12:05] davigar15, so I'm lost in how async helps you here [12:05] * facubatista is trying to understand, but it's so early in the morning here :) [12:05] Only to reuse the function I already made. Don't worry, you solved my problem [12:06] As I need to wait anyways, it doesn't help me at all [12:07] ack [12:09] one interesting thing for me, looking into this, is that there isn't AFAICT a way to tell a function from an async function before calling it [12:11] oh, inspect.iscoroutine [12:11] and iscoroutinefunction [12:11] fair'nuf [12:11] i first looked for async and only got isasyncgenerator[function] [12:16] Chipaca, I can not land charmcraft branch because "The base branch requires all commits to be signed", I'm reading about this (how to do that), but just telling you in case we have something misconfigured [12:16] hmm [12:16] facubatista: it's a toggle [12:17] facubatista: want me to un-toggle, or do you want to start pgp-signing commits? :-p [12:17] i'll toggle it as i suspect i may be the only one signing commits here [12:17] Chipaca, I can sign them [12:17] if I understand how :) [12:18] facubatista: made optional for now :) [12:19] Chipaca, what I don't understand is if I need to sign the commits in my branch, or sign the commit which merges my branch into master [12:20] facubatista: git config user.signkey "somekeyid", and git config commit.gpgsign true [12:20] facubatista: from memory [12:22] Chipaca, but that would sign the commits in *my branch*, not in master, is that what is needed? [12:22] facubatista: it'll sign your commits locally [12:23] facubatista: not on master, but i changed settings on charmcraft to use merge commits [12:23] facubatista: let's see how that works [13:02] > 16:32:32 as a charm developer, you need to call 'open-port' in order to tell Juju what to expose. <-- jam does this apply to k8s charms as well? [13:05] oh dang lunch [13:17] Chipaca, yay, I'm now "Verified" [13:20] facubatista: ✓ [13:23] * facubatista adds a ✓ to own CV [13:37] MarkMaglana, I'm not sure, as I believe part of the spec for the pod is what ports it is using. I haven't actively tested it either way. [14:08] jam: one thing we looked at and confirmed with facubatista on Friday [14:08] jam: is that Optional is not needed, as it's inferred automatically from =None [14:08] jam: which is nice :) [14:09] as in, if you have a =None, it'll be Optional [14:09] jam: yeah i suspected that was the case. [14:10] jam: surprisingly we have something marked Optional that _isn't_ =None [14:11] Chipaca, I think we have a couple things with default values, hence optional [14:12] ActiveStatus(message=''a) [14:12] etc [14:55] jam: hmm. I think Optional just means 'can be None', not 'has default values'; the default values need to match the explicit types (unless they're None, which makes the explicit type get promoted to Optional) [14:55] facubatista: any chance for a review on 284? [14:56] Chipaca, I was about to start my round on issues and prs [14:57] I'll start with 284, then [14:57] facubatista: also, you could land #273 :) [14:57] except conflicts [15:31] Chipaca, +1, with comment [15:31] * facubatista -> quick lunch before meeting [15:36] hi team, have a quick question: what's the right way to write a relation data inside of the event handler? I'm getting a "TypeError: 'Relation' object is not subscriptable" and I bet I'm doing something wrong... [15:38] vgrevtsev: relation.data[...] ? [15:38] vgrevtsev: instead of relation[...] [15:38] vgrevtsev: i guess :) [15:38] Neither `event.relation` using `event` object in the handler nor self.model.relations[_rel] .. didn't work [15:38] Ahh, `relation.data`, alright [15:38] vgrevtsev: 1 sec [15:38] Let me try [15:39] vgrevtsev: https://operator-framework.readthedocs.io/en/latest/#ops.model.Relation.data [15:40] ok, so `event.relation.data['foo'] = 'bar'` should work then? [15:41] vgrevtsev: event.relation.data[event.unit]['foo'] = 'bar' [15:41] no wait [15:42] that's the _other_ side, you can't write to that [15:42] vgrevtsev: event.relation.data[self.model.unit]['foo'] = 'bar' :) [15:42] that's the one you want [15:42] event.unit won't be "you" [15:42] so you can't write to it [15:43] well, so I can use [event.unit] to read the remote relation data being written by another charm (from another side of the relation) ? [15:43] yep [15:58] Chipaca, I can see that is what it means to 'typing', but that isn't what Optional means to me as a person [16:01] facubatista: you there? [16:01] yes [16:01] facubatista: ok :) [16:01] fighting auth [16:27] Chipaca: can a `ops.model.RelationDataContent` be casted to the regular dict to iterate over the relation data? (that's what I got after calling the `event.relation.data[event.unit]`) [16:28] vgrevtsev: ops.model.RelationDataContent is a MutableMapping, just use it as you would a dict and it should do the right thing [16:29] ah I see, will try, thanks a lot! [16:29] vgrevtsev: https://docs.python.org/3/library/collections.abc.html#collections.abc.MutableMapping if that helps [16:29] I'm on it atm :) [16:30] it's also a LazyMapping, which is the same thing but lazier ;-p [16:30] that helps - it tells me that .keys() and .items() are implemented in Mapping [16:30] so I can use them ^_^ [16:44] nice, that works, thanks again Chipaca :) [17:06] I am *so* happy we went with sphinx for the docs!!! [17:06] * Chipaca sings a ballad to intersphinx [17:08] with #285 things like MutableMapping will be a link straight into python 3's docs about that :-D [17:08] anyhoo, EOD for now. I'll bbl to tinker with ops.lib but might not come onto IRC as I need to do a large refactor to get things testable [17:08] 👋 [17:09] Chipaca, bye [22:03] * facubatista eods [23:43] what? but i just got here! was it something i said??