Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nixos/neo4j: Update module, make compatible with neo4j 3.4 #42748

Merged
merged 1 commit into from Jul 16, 2018

Conversation

patternspandemic
Copy link
Contributor

@patternspandemic patternspandemic commented Jun 28, 2018

Motivation for this change

The nixos/neo4j service module was around a year out of date, and incompatible with recent releases of the neo4j package. This change updates the module into working order and adds a number of other useful options to the module.

Some points:

  • Testing of most options was performed manually.
  • Testing the building of doc strings still needs to occur, as xsltproc kept segfaulting during my attempts.
    [Performed]
  • Options of the previous module version are not really compatible with how the server configs now, thus decided to remove existing renamed option, and not add any more.
    [Additions made to rename.nix]
  • Not sure if adding 8 mkRemovedOptionModule for the older options makes sense.
    [Additions made to rename.nix]
  • Maybe backport to 18.03 along with the neo4j package. [Informed this doesn't occur]

Cheers

Things done
  • Tested using sandboxing (nix.useSandbox on NixOS, or option sandbox in nix.conf on non-NixOS)
  • Built on platform(s)
    • NixOS
    • macOS
    • other Linux distributions
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nox --run "nox-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Determined the impact on package closure size (by running nix path-info -S before and after)
  • Fits CONTRIBUTING.md.


# Place the configuration where Neo4j can find it.
ln -fs ${serverConfig} ${toString cfg.directories.home}/conf/neo4j.conf
if [ "$(id -u)" = 0 ]; then chown -R neo4j ${toString cfg.directories.home}; fi
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this condition always true?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like it. This check is in the existing module, and I hadn't looked closely at it, apart from updating the directory ref.

for this policy to be found in the <literal>baseDirectory</literal>,
or the absolute path to the certificate file. It is mandatory
that a certificate can be found or generated.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To get the docs rendered as intended, these spaces need to have a

</para>
<para>

Also applies to the other options where this is used.


The public certificate is required to be duplicated to the
directory holding trusted certificates as defined by the
<literal>trustedDir</literal> option.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All these should be replaced with the dedicated <option>someOption</option> xml annotation (in all options).

default = false;
description = ''
Enable a remote shell server which Neo4j Shell clients can log in to.
Only applicable to <literal>neo4j-shell</literal>.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's <command></command> for that

default = 7474;
type = types.int;
workerCount = mkOption {
type = types.either (types.enum [ "Available Processors" ]) (types.ints.between 1 44738);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to just use types.nullOr, null signifying all available processors. Also why is this number limited to exactly 44738?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the valid range of values for the option as described by the configuration setting. I chose an enum to make it easy to understand what the actual Neo4j config setting defaults to. Using nullOr with mention of what the null means in the docstring works too, I just thought using the enum would be a more direct way of saying so.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or even: Use the integer 0 to represent all available ones. Nix does the same with the --cores argument / nix.buildCores option.

dbms.udc.enabled=${boolToString cfg.udc.enable}

# Extra Configuration
${cfg.extraServerConfig}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this module is a good candidate to convert to a semantic config thing, similar to how I did it in #41467. The idea is to represent the full config as a Nix value, so something like

services.neo4j.config = {
  dbms.jvm.additional = [
    "-XX:+UseG1GC"
    ...
  ];
  dbms.shell.enabled = true
}

Then use a function to convert this to a neo4j readable config file. The advantages are:

  • Users can easily override whatever they want instead of being bounded to the given config file
  • The config gets a free syntax check
  • More modular via NixOS module system, merging of values
  • This module gets cleaner, less stringy

I'll gladly help with getting this to work

It's not necessary, but I'm very much in favor of doing this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this module is a good candidate to convert to a semantic config thing

For the entire module or just the extraServerConfig option?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The entire config file, instead of using giant strings to declare the config, you'd use nix values. See this as an example of how assigning default values would look like.

dbms.ssl.policy.${name}.revoked_dir=${builtins.replaceStrings ["__policyname__"] [name] (toString conf.revokedDir)}
dbms.ssl.policy.${name}.tls_versions=${concatStringsSep "," conf.tlsVersions}
dbms.ssl.policy.${name}.trust_all=${boolToString conf.trustAll}
dbms.ssl.policy.${name}.trusted_dir=${builtins.replaceStrings ["__policyname__"] [name] (toString conf.trustedDir)}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This __policyname__ replacement business isn't really necessary, because in the end you're gonna have the name at the definition anyways:

services.neo4j.policies.foo = {
  trustedDir = "/some/foo";
}

I'll comment below how you can use the policy name in the options default value without having to use this replacement.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I figured there was a way but couldn't pinpoint it..

absolute path.
'';
};

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To get rid of the __policyname__ thing, use type = with types; attrsOf (submodule ({ name, ... }: { in line 354, and add a section here like this:

config = {
  trustedDir = mkDefault "${cfg.directories.certificates}/${name}/trusted";
  ...
}

And remove the defaults declared in the options.

@infinisil
Copy link
Member

Also, how does this module look regarding backwards-compatibility? Seems like the old options got removed.

@patternspandemic
Copy link
Contributor Author

The module was not kept up to date with newer Neo4j package releases. The existing module's option declaration's stem from #19601, corresponding to Neo4j 3.0.6 (package is currently at 3.4.1). Furthermore, the existing module contains non-configurable settings that have been deprecated and since removed from most recent config setting docs, for example dbms.connector.http.type. I am not sure how current versions of Neo4j handle deprecated settings this old in its configuration.

Putting work toward backward-compatibility at this point may not be worth much.

@infinisil
Copy link
Member

Hmm right, I'm fine with deprecating the options, but you should add a mkRemovedOptionModule for each removed option, so users of them aren't completely lost.

@patternspandemic
Copy link
Contributor Author

Thank you for the review and suggestions. I'll get to these changes soon.

@patternspandemic
Copy link
Contributor Author

All requested changes made with the exception of the 'semantic config thing', which I think is a good idea, though I haven't the time to rework it just yet. It should require much less upkeep of the module as changes / deprecations are made to Neo4j config settings over time.

Copy link
Member

@infinisil infinisil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's coming along well, I hope you don't mind the thorough review :)


<para>The public certificate is required to be duplicated to the
directory holding trusted certificates as defined by the
<option>trustedDir</option> option.</para>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Nix manual wraps all description fields with a <para></para> already, so you can (and have to) remove the first <para> and the last </para> to make it work. Use nix-build nixos/release.nix -A manual.x86_64-linux to check that the manual builds. It also produces result/share/doc/nixos/options.html you can view in a browser to see what the rendered description looks like.


revokedDir = mkOption {
type = types.path;
default = "${cfg.directories.certificates}/${name}/revoked";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, when the user sets baseDirectory of some policy, the revokedDir still uses the "old" default base directory ("${cfg.directories.certificates}/${name}"). To have it use the policies baseDirectory, you can add config to the submodules arguments (next to name), and use default = "${config.baseDirectory}/revoked"

Same for trustedDirs

certificates = mkOption {
type = types.path;
default = "${cfg.directories.home}/certificates";
description =''
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: space missing


sslPolicy = mkOption {
type = types.str;
default = "legacy";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What allowed values are there for this? Is it just "legacy" and the ones defined in the policies option? If so, you could add an assertion that checks this (can't use types.enum, because it depends on the users config), something like the following in this modules config section:

let policies = ["legacy"] ++ map (p: p.name) cfg.policies; in
...
assertions = [{
  assertion = elem cfg.bolt.sslPolicy policies;
  message = "Invalid `services.neo4j.bolt.sslPolicy`, valid ones are: ...";
}]

Although, this might not work 100% reliably because of the extraConfig option (since if policies can be declared there, this module won't know about them).

The same for the other options that use policies.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a few assertions.

description = ''
Whether to enable Neo4j Community Edition.
'';
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nixpick: enable should be the topmost option. (sidenote: The manual also uses this special ordering rule when building the manual, so you'll always find enable options at the top)

Also, you could use mkEnableOption "Neo4j Community Edition"

@patternspandemic
Copy link
Contributor Author

I hope you don't mind the thorough review

It is appreciated, and expected. I am learning much. Thank you.

@patternspandemic patternspandemic force-pushed the neo4j-service branch 2 times, most recently from c050e94 to a9c7258 Compare July 3, 2018 23:44

mkIf cfg.enable {
assertions = [
{ assertion = !(elem "legacy" policyNameList);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could remove those parens because function application has a higher precedence than the ! operator

I didn't think of this assertion, very nice :o

There's a nice list of all precedences in the wiki: https://nixos.wiki/wiki/Nix_Expression_Language#Operators :)


preStart = ''
# Directories Setup
mkdir -m 0700 -p ${toString cfg.directories.home}/{certificates,conf,data,import,logs,plugins}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be adjusted to the options for the certificate, data, import and plugins paths. Probably just not creating those when they're not the default values.

A neat way of knowing whether the default value is used (without having to do string comparison) is to add options to the argument list at the top, then checking options.services.neo4j.directories.certificates.highestPrio >= 1500. This value 1500 comes from

mkOptionDefault = mkOverride 1500; # priority of option defaults
which is used for the default attribute in option declarations.

A filter for that over builtins.attrValues options.services.neo4j.directories should then get you a list of directories to create. (use .value to get the value of an option, config.some.option == options.some.option.value)

# SSL Policies Directory setup
# Only generate required directories when default certificates and baseDirectory is used.
${concatStringsSep "\n" (mapAttrsToList (name: value:
if cfg.directories.home + "/certificates/" + name == value.baseDirectory then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be the policies directory?

Also, you can use the same highestPrio thing here to not have to even do this string comparison.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can use the same highestPrio thing here

How does one access an attribute within the policy without knowing its name?
options.services.neo4j.ssl.policies.?.baseDirectory.highestPrio

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

filter builtins.attrValues options.services.neo4j.ssl.policies based on (opt: opt.baseDirectory.highestPrio < 1500), then an if on whether there are any results at all, then a concatMapStringsSep " " over (opt: opt.baseDirectory.value).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@infinisil

filter builtins.attrValues options.services.neo4j.ssl.policies based on (opt: opt.baseDirectory.highestPrio < 1500)

This doesn't work because options.services.neo4j.ssl.policies is an option itself, and the attrValues of options.services.neo4j.ssl.policies are not options as you expected. A trace of the attrNames is:

[ "_type" "declarations" "default" "definitions" "description" "files" "highestPrio" "isDefined" "loc" "options" "type" "value" ]

The options attribute of this set sounded promising, but alas is empty.

I attempted to access options of a specific defined policy by first collecting the policy names, which also fails, i.e. options.services.neo4j.ssl.policies."name" results is attribute 'name' missing, even when the 'name' policy is defined.

The current push incorrectly uses the definitions attribute, with the assumption that any option not defined therein must still be at its default. Incorrectly in that it doesn't merge all attrsets in definitions before checking for this assumption (naively chooses the first definition attrset).

Of course it's Nixos' job to merge these definitions, but I still cannot figure out how/where to access a policy's option attrset.

ln -fs ${serverConfig} ${toString cfg.directories.home}/conf/neo4j.conf

# Ensure neo4j user ownership
chown -R neo4j ${toString cfg.directories.home}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to remove all toString functions from all those directories. How it is now would make certificates = ./path/to/certs behave as if you specified "/absolute/path/to/certs", but what one would expect (just from what all other modules do) is that ./path/to/certs gets imported into the store and result in "/nix/store/<hash>-certs". toString can still be applied from the user if it's what they need like this.

@patternspandemic
Copy link
Contributor Author

I feel like I'm close, but got stuck. :\ I could use some help.

validPolicyNameList = ["legacy"] ++ policyNameList;
validPolicyNameString = concatStringsSep ", " validPolicyNameList;

defaultDirectoriesList = builtins.filter (dir: dir.highestPrio >= 1500) (builtins.attrValues options.services.neo4j.directories);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@infinisil I'm not understanding something about the list of option values as generated here.

while evaluating anonymous function at /home/pattern/repos/nixpkgs/nixos/modules/services/databases/neo4j.nix:570:49, called from undefined position:
value is a list while a set was expected, at /home/pattern/repos/nixpkgs/nixos/modules/services/databases/neo4j.nix:570:54

I thought builtins.attrValues options.services.neo4j.directories would return a list of the sets defined in options.services.neo4j.directories

I think I'm on the right path, but am stuck.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I got it, this is a fix:

diff --git a/nixos/modules/services/databases/neo4j.nix b/nixos/modules/services/databases/neo4j.nix
index bdf6f44dd1d..50c386ce9b6 100644
--- a/nixos/modules/services/databases/neo4j.nix
+++ b/nixos/modules/services/databases/neo4j.nix
@@ -567,11 +567,11 @@ in {
       validPolicyNameList = ["legacy"] ++ policyNameList;
       validPolicyNameString = concatStringsSep ", " validPolicyNameList;
 
-      defaultDirectoriesList = builtins.filter (dir: dir.highestPrio >= 1500) (builtins.attrValues options.services.neo4j.directories);
+      defaultDirectoriesList = builtins.filter (dir: isOption dir && dir.highestPrio >= 1500) (builtins.attrValues options.services.neo4j.directories);
       certDirIsDefault = options.services.neo4j.directories.certificates.highestPrio >= 1500;
       defaultPoliciesList =
         if !certDirIsDefault then []
-        else builtins.filter (pol: pol.baseDirectory.highestPrio >= 1500) (builtins.attrValues options.services.neo4j.ssl.policies);
+        else builtins.filter (pol: isOption pol && pol.baseDirectory.highestPrio >= 1500) (builtins.attrValues options.services.neo4j.ssl.policies);
     in
 
     mkIf cfg.enable {

The reason for this is that options.services.neo4j.directories actually also includes a value for _definedNames, which is a list used by the module system probably, only just now realized this, sorry! The fix just makes sure that all values are options via isOption.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Admittedly this is a bit ugly, but imo that's better than the alternative (explicitly repeating code for all 5 directories)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@infinisil highestPrio doesn't seem to exist on these sets.

defaultDirectoriesList = builtins.filter (
  dir: (builtins.trace dir dir).highestPrio >= 1500
) (builtins.filter (dir: isOption dir) (builtins.attrValues options.services.neo4j.directories));
trace: { _type = "option"; declarations = <CODE>; default = <CODE>; definitions = <CODE>; description = "Directory for storing ..."; files = <CODE>; isDefined = <CODE>; loc = <CODE>; options = <CODE>; type = <CODE>; value = <CODE>; }

...
attribute 'highestPrio' missing, at /home/pattern/repos/nixpkgs/nixos/modules/services/databases/neo4j.nix:574:14

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cannot reproduce: https://gist.github.com/8f954a39abcdf0f9e4903057134a6f69

I'm using the latest commit from here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@infinisil This appears to be due to my building against a branch made from my local nixos-version (18.03 stable). Looks like these commits made re: highestPrio 4017fdc and 441796c are found in nixos-unstable, but not 18.03. I will work to build agains unstable instead. I suppose this technique would then not be compatible for backport to 18.03?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updates won't get backported anyways.

@infinisil
Copy link
Member

Here's a neat way to debug such things:

  • Go to the nixpkgs checkout with your changes and write a simple configuration.nix in there (e.g. { services.neo4j = { enable = true; directories.home = "/foo"; }; })
  • Assign an alias like alias ev="nix-instantiate --eval nixos --arg configuration ./configuration.nix -A"
  • Use it to query values (use tab-completion for maximum comfyness):
    • ev options.services.neo4j.directories
    • ev config.system.build.toplevel to do a system evaluation

I usually also add { fileSystems."/".device = "x"; boot.loader.grub.device = "nodev"; } to the config, to make the system evaluation happy and not throw assertions.

@patternspandemic patternspandemic force-pushed the neo4j-service branch 2 times, most recently from 870874b to eaeb7ac Compare July 11, 2018 16:56

environment.systemPackages = [ cfg.package ];
# The attr set of configured policies and their options, NOT including option defaults.
policyDefinitions = builtins.head (options.services.neo4j.ssl.policies.definitions);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An incorrect naive solution. To be replaced.

@infinisil
Copy link
Member

Ah got it, I actually didn't know this either before just now. The reason there's so much trouble with this is because it's hard to get the actual option types out of the submodule. A solution is to use an internal option within the submodule to export the info one needs:

diff --git a/nixos/modules/services/databases/neo4j.nix b/nixos/modules/services/databases/neo4j.nix
index 489410dd15a..4cd707e08cd 100644
--- a/nixos/modules/services/databases/neo4j.nix
+++ b/nixos/modules/services/databases/neo4j.nix
@@ -5,6 +5,8 @@ with lib;
 let
   cfg = config.services.neo4j;
 
+  certDirOpt = options.services.neo4j.directories.certificates;
+
   sslPolicies = mapAttrsToList (
     name: conf: ''
       dbms.ssl.policy.${name}.allow_key_generation=${boolToString conf.allowKeyGeneration}
@@ -392,7 +394,7 @@ in {
     };
 
     ssl.policies = mkOption {
-      type = with types; attrsOf (submodule ({ name, config, ... }: {
+      type = with types; attrsOf (submodule ({ name, config, options, ... }: {
         options = {
 
           allowKeyGeneration = mkOption {
@@ -531,7 +533,27 @@ in {
             '';
           };
 
+          directoriesToCreate = mkOption {
+            type = types.listOf types.path;
+            internal = true;
+            readOnly = true;
+            description = ''
+              Directories of this policy that will be created automatically.
+              This includes all options of type path that are left at the
+              default value.
+            '';
+          };
+
         };
+
+        config.directoriesToCreate = let
+            needsDir = opt: isOption opt && opt.type == types.path && opt.highestPrio >= 1500;
+          in optionals (certDirOpt.highestPrio >= 1500 && options.baseDirectory.highestPrio >= 1500) (map (opt: opt.value) (filter needsDir (attrValues options)));
+
+        # Alternatively:
+        # map (opt: opt.value) (filter (opt: opt.highestPrio >= 1500)
+        #  [ options.baseDirectory options.revokedDir options.trustedDir ]
+
       }));
       default = {};
       description = ''
@@ -564,32 +586,14 @@ in {
   config =
     let
       # Assertion helpers
-      policyNameList = (attrNames cfg.ssl.policies);
-      validPolicyNameList = ["legacy"] ++ policyNameList;
+      policyNameList = attrNames cfg.ssl.policies;
+      validPolicyNameList = [ "legacy" ] ++ policyNameList;
       validPolicyNameString = concatStringsSep ", " validPolicyNameList;
 
       # A list of directories options left at their default.
-      defaultDirectoriesOptionList = builtins.filter (dir: isOption dir && dir.highestPrio >= 1500) (builtins.attrValues options.services.neo4j.directories);
-
-      # Whether directories.certificates was left at its default.
-      certDirIsDefault = options.services.neo4j.directories.certificates.highestPrio >= 1500;
-
-      # The attr set of configured policies and their options, NOT including option defaults.
-      policyDefinitions = builtins.head (options.services.neo4j.ssl.policies.definitions);
-
-      # Policies that retain a default baseDirectory.
-      policiesWithDefaultBase = filterAttrs (n: v: !hasAttrByPath [n "baseDirectory"] policyDefinitions) cfg.ssl.policies;
-
-      policyDirectoriesToCreate =
-        # Only add policy directories when certificates directory is left at its default.
-        if certDirIsDefault then
-          # Add policy baseDirectories left at their default
-          (mapAttrsToList (n: v: v.baseDirectory) policiesWithDefaultBase)
-          # Add policy revokedDir left at their default
-          ++ (mapAttrsToList (n: v: v.revokedDir) (filterAttrs (n: v: !hasAttrByPath [n "revokedDir"] policyDefinitions) policiesWithDefaultBase))
-          # Add policy trustedDir left at their default
-          ++ (mapAttrsToList (n: v: v.trustedDir) (filterAttrs (n: v: !hasAttrByPath [n "trustedDir"] policyDefinitions) policiesWithDefaultBase))
-        else [];
+      defaultDirectoriesOptionList = filter (dir: isOption dir && dir.highestPrio >= 1500) (attrValues options.services.neo4j.directories);
+
+      policyDirectoriesToCreate = concatMap (pol: pol.directoriesToCreate) (attrValues cfg.ssl.policies);
     in
 
     mkIf cfg.enable {
@@ -597,9 +601,9 @@ in {
         { assertion = !elem "legacy" policyNameList;
           message = "The policy 'legacy' is special to Neo4j, and its name is reserved."; }
         { assertion = elem cfg.bolt.sslPolicy validPolicyNameList;
-          message = "Invalid policy assigned: `services.neo4j.bolt.sslPolicy = ${cfg.bolt.sslPolicy}`, defined policies are: ${validPolicyNameString}"; }
+          message = "Invalid policy assigned: `services.neo4j.bolt.sslPolicy = \"${cfg.bolt.sslPolicy}\"`, defined policies are: ${validPolicyNameString}"; }
         { assertion = elem cfg.https.sslPolicy validPolicyNameList;
-          message = "Invalid policy assigned: `services.neo4j.https.sslPolicy = ${cfg.https.sslPolicy}`, defined policies are: ${validPolicyNameString}"; }
+          message = "Invalid policy assigned: `services.neo4j.https.sslPolicy = \"${cfg.https.sslPolicy}\"`, defined policies are: ${validPolicyNameString}"; }
       ];
 
       systemd.services.neo4j = {

internal = true means that it won't show up in the man page, and readOnly = true means you can only assign it once, and that is being done in the config section -> you can't assign it at all in your configuration.nix, aka it's read only.

@patternspandemic
Copy link
Contributor Author

@infinisil Thanks again for your help on this!

Copy link
Member

@infinisil infinisil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 minor nitpicks and other than that this is looking good to me, great work!

Have you tested it after all these changes again? They were only changes to the module, which shouldn't really modify behavior, but you never know.


environment.systemPackages = [ cfg.package ];
# Create other sub-directories and policy directories that have been left at their default.
${concatStringsSep "\n" (map (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's concatMapStringsSep :)

validPolicyNameString = concatStringsSep ", " validPolicyNameList;

# Capture various directories left at their default so they can be created.
defaultDirectoriesToCreate = (map (opt: opt.value) (filter isDefaultPathOption (attrValues options.services.neo4j.directories)));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The outer pair of parens can be removed

@patternspandemic
Copy link
Contributor Author

Have you tested it after all these changes again?

Indeed I have tested manually each time. Of course at some point a module test would be best.

Copy link
Member

@infinisil infinisil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect, thanks, this is looking good to me! Certainly a more complicated module than usual, great work!

I'll merge this soon if nobody complains :)

@infinisil infinisil merged commit f2632f5 into NixOS:master Jul 16, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants