Nix coding pattern: merging two conditional lists created with mkIf

Advertisements

When given two lists each of which are conditional on basis of mkIf, how to merge those two lists (akin to mkMerge for sets)?
I have run into the following pattern several times now and I cannot seem to find documentation explaining how to idiomatically solve this.

Say you’re starting out with this snippet:

someConfigValue = mkIf (cfg.condition1) [ "some value 1" ];

Then you add another conditional value:

someConfigValue = [
  (mkIf (cfg.condition1) [ "some value 1" ])
  (mkIf (cfg.condition2) [ "some value 2" ])
];

In the specific case at hand (trying to pass this to systemd.services.<name>.LoadCredential) I get the following error since the internal representation of the two mkIf values are sets:

error: cannot coerce a set to a string

Using mkMerge does not seem to work either (since it takes a list of sets and merges those sets).
I could replace the mkIfs with optionals and then concatenate the lists using ++, but that’s dumping all the module logic, so I’m not sure whether that’s the right choice here.

>Solution :

Ordinarily, I would use optionals for something like this.

If you really want to make it mergable, I think you can instead put whateverService.serviceConfig.LoadCredentials = [ "cred 1" ]; on one side of a merge and whateverService.serviceConfig.LoadCredentials = [ "cred 2" ]; on the other side, and the standard merging logic will put them in the same list.

This more or less results in just pushing someConfigValue in one level:

config = mkMerge [
  (mkIf (cfg.condition1) { someConfigValue = [ "some value 1" ]; })
  (mkIf (cfg.condition2) { someConfigValue = [ "some value 2" ]; })
];

Which is more or less how I tend to see mkIf used: It predicates whole sections of config at the top level, rather than individual values inside of config. Individual values tend to use things like optionals or optionalString.

Leave a ReplyCancel reply