NixOS Module System | 146 Members | |
| 29 Servers |
| Sender | Message | Time |
|---|---|---|
| 14 Nov 2024 | ||
| * nbp: thanks for the feedback! First I want to say I'm convinced these contracts will really help in nixpkgs but I'm still experimenting on the UX side. So don't take my I considered enums at the start, but the problem I have with those is it's not easily extendable by the end user without modifying nixpkgs directly. At least I don't think so? What I have currently is the following. My "best" and most recent contracts are currently the backup and database backup contracts. The former is for backing up files, the latter for backing up the output of a command (like pg_dump) without going through an intermediate file. (writing this down, I should probably find a better name than database backup) This is the backup contract and the database backup one I have now. They're both just attrsets with some pre-defined schema: A requester of the backup contract, for example Nextcloud which wants to be backed up, would then provide a A provider of the backup contract, for example Restic, would provide an attribute that uses the Putting both sides of the contract together is the end user's responsibility. Here, for backing up Nextcloud files with Restic, it looks like so:
Assuming
The beauty here is that if you had a Vaultwarden instance you want to backup, you can just add the following snippet without knowing anything about how to backup Vaultwarden:
Similarly, if you wanted to also use BorgBackup to backup Nextcloud and Vaultwarden, you can also just copy paste the snippets and just
Of course, you'd need to configure Nextcloud, Vaultwarden, Restic and BorgBackup with specific options. But this snippet is just showing the pluming going on. If you're curious, backing up Vaultwarden is not necessarily complicated. But still, hiding it from the end user is nice. Using the database backup contract is as easy:
Here's the PostgreSQL provider side if you're curious. But now comes the even better part IMO. How do you make sure the Restic and BorgBackup are equivalent (from the contract perspective)? With generic tests! Here's the one for backup contract and here's the one for database backup contract. They are generic because they're a function taking in a location to a module so you plug in a module that provides the contract and the test will make sure it has the same behavior. Of course you actually need to call that function to test something and that is done here and here respectively for the backup and database backup contract. These generic tests have a lot of value IMO. So yeah, that's where I'm at with contracts. If you spelunk in the code of the project, you'll see I have a contract for secrets and ssl. They predate this One last thing, you'll note that the restore script and backup service in the | 16:36:21 | |
| * nbp: thanks for the feedback! First I want to say I'm convinced these contracts will really help in nixpkgs but I'm still experimenting on the UX side. So don't take my I considered enums at the start, but the problem I have with those is it's not easily extendable by the end user without modifying nixpkgs directly. At least I don't think so? What I have currently is the following. My "best" and most recent contracts are currently the backup and database backup contracts. The former is for backing up files, the latter for backing up the output of a command (like pg_dump) without going through an intermediate file. (writing this down, I should probably find a better name than database backup) This is the backup contract and the database backup one I have now. They're both just attrsets with some pre-defined schema: A requester of the backup contract, for example Nextcloud which wants to be backed up, would then provide a A provider of the backup contract, for example Restic, would provide an attribute that uses the Putting both sides of the contract together is the end user's responsibility. Here, for backing up Nextcloud files with Restic, it looks like so:
Assuming
The beauty here is that if you had a Vaultwarden instance you want to backup, you can just add the following snippet without knowing anything about how to backup Vaultwarden:
Similarly, if you wanted to also use BorgBackup to backup Nextcloud and Vaultwarden, you can also just copy paste the snippets and just
Of course, you'd need to configure Nextcloud, Vaultwarden, Restic and BorgBackup with specific options. But this snippet is just showing the pluming going on. If you're curious, backing up Vaultwarden is not necessarily complicated. But still, hiding it from the end user is nice. Using the database backup contract is as easy:
Here's the PostgreSQL provider side if you're curious. But now comes the even better part IMO. How do you make sure the Restic and BorgBackup are equivalent (from the contract perspective)? With generic tests! Here's the one for backup contract and here's the one for database backup contract. They are generic because they're a function taking in a location to a module so you plug in a module that provides the contract and the test will make sure it has the same behavior. Of course you actually need to call that function to test something and that is done here for the backup and database backup contract. These generic tests have a lot of value IMO. So yeah, that's where I'm at with contracts. If you spelunk in the code of the project, you'll see I have a contract for secrets and ssl. They predate this One last thing, you'll note that the restore script and backup service in the | 16:36:46 | |
| enum are externally extendable in the module system. This is how desktopManagers / windowManagers are handled. | 16:40:38 | |
| * enum are externally extendable in the module system. This is how desktopManagers / windowManagers are handled. Or why they got added a while back.
makes sense, as opposed to many other languages, because options can be extended by multiple modules. Thus if all providers were to add extra declarations, you could have an option which enumerate all services which could be used as a provider. | 16:48:23 | |
| Here is an example, where a module declare an And another module provide an implementation for it: | 16:59:10 | |
The module which declare the enum [] is equivalent to a contract and the module which declares it as enum [ "its-own-name" ] is equivalent to a provider. | 17:02:09 | |
| That’s interesting. I have no idea how to compare both solutions, what’s their respective drawbacks and advantages. I took the structural typing approach because I knew that from my programming in Python and Go and it sticked with me. One potential drawback is discoverability although there’s surely a way to remediate to that. | 19:12:56 | |
| 15 Nov 2024 | ||
| 10:17:04 | ||
| 15:08:21 | ||
| 17 Nov 2024 | ||
| 02:28:12 | ||
| 02:38:28 | ||
| Apologies in advance for the massive text block, I'm gonna drop this here because I suspect I'll eventually get more visibility from people who can answer this. | 02:56:13 | |
| Could I get some insight into how the module system evaluates a type Here's a very minimal example of my issue including a description of what I'm expecting to happen.
You can save the above and use
From what I understand about both priorities and merging, The weirdest part is yet to come.. when I switch them around, as in declare | 02:56:21 | |
| 18 Nov 2024 | ||
| From my point of view the fact that the priority leaks in the value is an issue on its own. This should not be the case. All properties should have been discharged before calling the merge function … except when evaluating submodules, and even then this is open for debate. | 10:38:57 | |
Then the update (//) operator is not commutatif, as such the merging of values from the same priority should be ordered.Use mkOrder / mkBefore / mkAfter to determine this order.The order in which NixOS compute values is deliberately left undefined. | 10:40:49 | |
| Oh … how did I missed it … Properties are evaluated at options, not after, which is why using the value
Which does not have the priority leaking in the value of the option. | 12:58:17 | |
| oh my it was so obvious too | 21:38:52 | |
| thanks for the response thats honestly somewhat embarrassing that i didnt catch that earlier | 21:39:14 | |
| because like you said, the priority being there was a big sign | 21:39:26 | |
| 19 Nov 2024 | ||
In reply to @frontear:matrix.orgHey sometimes you’re too much in the weeds, seeing the big picture becomes hard. Definitely happened to me more than once. | 12:39:21 | |
| 20 Nov 2024 | ||
| 00:59:38 | ||
| 21 Nov 2024 | ||
| 02:51:47 | ||
| 13:46:18 | ||
| 25 Nov 2024 | ||
| 10:00:58 | ||
| 27 Nov 2024 | ||
| 18:19:03 | ||
| 6 Dec 2024 | ||
| 03:43:51 | ||
| 11 Dec 2024 | ||
| 14:19:11 | ||
| 12 Dec 2024 | ||
| 14:34:25 | ||
| 13 Dec 2024 | ||
| 09:28:33 | ||
| Hi all I've come across a fun problem recently. I maintain a set of modules, and previously I had an option in a submodule, but now I've made it a regular (top-level) option. Per usual with changes like this, I wanted to use After doing some digging, I'm assuming this is because submodules sort of strip out the regular option data of their inner values, and only expose the fully evaluated configuration. Am I right here? Is there a good way around this? Here's a minimum repro:
| 09:33:27 | |