summary refs log tree commit diff
diff options
context:
space:
mode:
authorNicolas B. Pierron <nicolas.b.pierron@gmail.com>2015-11-18 00:26:00 +0000
committerNicolas B. Pierron <nicolas.b.pierron@gmail.com>2015-11-19 20:58:45 +0000
commita5992ad61b314104aff7e28a41ce101a1b0e7c35 (patch)
tree7fbf4a4ffb401b4a6d1a0c97357625d77cc4dc6b
parentbd33a4149364ee5123070fe6e706876fa2ebf984 (diff)
downloadnixpkgs-a5992ad61b314104aff7e28a41ce101a1b0e7c35.tar
nixpkgs-a5992ad61b314104aff7e28a41ce101a1b0e7c35.tar.gz
nixpkgs-a5992ad61b314104aff7e28a41ce101a1b0e7c35.tar.bz2
nixpkgs-a5992ad61b314104aff7e28a41ce101a1b0e7c35.tar.lz
nixpkgs-a5992ad61b314104aff7e28a41ce101a1b0e7c35.tar.xz
nixpkgs-a5992ad61b314104aff7e28a41ce101a1b0e7c35.tar.zst
nixpkgs-a5992ad61b314104aff7e28a41ce101a1b0e7c35.zip
Add a way to pin a NixOS version within the module system.
This modification add a way to re-evaluate the module system with a
different version of NixOS, or with a different set of arguments.
-rw-r--r--nixos/default.nix16
-rw-r--r--nixos/doc/manual/configuration/configuration.xml1
-rw-r--r--nixos/doc/manual/default.nix1
-rw-r--r--nixos/doc/manual/release-notes/rl-unstable.xml20
-rw-r--r--nixos/modules/misc/nixos.nix82
-rw-r--r--nixos/modules/misc/nixos.xml84
-rw-r--r--nixos/modules/module-list.nix1
-rw-r--r--nixos/release.nix1
-rw-r--r--nixos/tests/nixos-pin-version.nix57
9 files changed, 259 insertions, 4 deletions
diff --git a/nixos/default.nix b/nixos/default.nix
index 5d69b79e13a..6359d10c880 100644
--- a/nixos/default.nix
+++ b/nixos/default.nix
@@ -1,12 +1,20 @@
 { configuration ? import ./lib/from-env.nix "NIXOS_CONFIG" <nixos-config>
 , system ? builtins.currentSystem
+, extraModules ? []
+  # This attribute is used to specify a different nixos version, a different
+  # system or additional modules which might be set conditionally.
+, reEnter ? false
 }:
 
 let
+  reEnterModule = {
+    config.nixos.path = with (import ../lib); mkIf reEnter (mkForce null);
+    config.nixos.configuration = configuration;
+  };
 
   eval = import ./lib/eval-config.nix {
     inherit system;
-    modules = [ configuration ];
+    modules = [ configuration reEnterModule ] ++ extraModules;
   };
 
   inherit (eval) pkgs;
@@ -14,14 +22,14 @@ let
   # This is for `nixos-rebuild build-vm'.
   vmConfig = (import ./lib/eval-config.nix {
     inherit system;
-    modules = [ configuration ./modules/virtualisation/qemu-vm.nix ];
+    modules = [ configuration reEnterModule ./modules/virtualisation/qemu-vm.nix ] ++ extraModules;
   }).config;
 
   # This is for `nixos-rebuild build-vm-with-bootloader'.
   vmWithBootLoaderConfig = (import ./lib/eval-config.nix {
     inherit system;
     modules =
-      [ configuration
+      [ configuration reEnterModule
         ./modules/virtualisation/qemu-vm.nix
         { virtualisation.useBootLoader = true; }
       ];
@@ -30,7 +38,7 @@ let
 in
 
 {
-  inherit (eval) config options;
+  inherit (eval.config.nixos.reflect) config options;
 
   system = eval.config.system.build.toplevel;
 
diff --git a/nixos/doc/manual/configuration/configuration.xml b/nixos/doc/manual/configuration/configuration.xml
index 8fde0dc7e61..afffd60bc48 100644
--- a/nixos/doc/manual/configuration/configuration.xml
+++ b/nixos/doc/manual/configuration/configuration.xml
@@ -26,6 +26,7 @@ effect after you run <command>nixos-rebuild</command>.</para>
 
 <!-- FIXME: auto-include NixOS module docs -->
 <xi:include href="postgresql.xml" />
+<xi:include href="nixos.xml" />
 
 <!-- Apache; libvirtd virtualisation -->
 
diff --git a/nixos/doc/manual/default.nix b/nixos/doc/manual/default.nix
index 87964e27bb9..844cba57cd8 100644
--- a/nixos/doc/manual/default.nix
+++ b/nixos/doc/manual/default.nix
@@ -55,6 +55,7 @@ let
       cp -prd $sources/* . # */
       chmod -R u+w .
       cp ${../../modules/services/databases/postgresql.xml} configuration/postgresql.xml
+      cp ${../../modules/misc/nixos.xml} configuration/nixos.xml
       ln -s ${optionsDocBook} options-db.xml
       echo "${version}" > version
     '';
diff --git a/nixos/doc/manual/release-notes/rl-unstable.xml b/nixos/doc/manual/release-notes/rl-unstable.xml
index 573b99d4902..65aa36586cb 100644
--- a/nixos/doc/manual/release-notes/rl-unstable.xml
+++ b/nixos/doc/manual/release-notes/rl-unstable.xml
@@ -6,6 +6,26 @@
 
 <title>Unstable</title>
 
+<para>In addition to numerous new and upgraded packages, this release
+has the following highlights:</para>
+
+<itemizedlist>
+
+  <listitem>
+    <para>You can now pin a specific version of NixOS in your <filename>configuration.nix</filename>
+    by setting:
+
+<programlisting>
+nixos.path = ./nixpkgs-unstable-2015-12-06/nixos;
+</programlisting>
+
+    This will make NixOS re-evaluate your configuration with the modules of
+    the specified NixOS version at the given path.  For more details, see
+    <xref linkend="module-misc-nixos" /></para>
+  </listitem>
+
+</itemizedlist>
+
 <para>When upgrading from a previous release, please be aware of the
 following incompatible changes:</para>
 
diff --git a/nixos/modules/misc/nixos.nix b/nixos/modules/misc/nixos.nix
new file mode 100644
index 00000000000..356129211d0
--- /dev/null
+++ b/nixos/modules/misc/nixos.nix
@@ -0,0 +1,82 @@
+{ config, options, lib, ... }:
+
+# This modules is used to inject a different NixOS version as well as its
+# argument such that one can pin a specific version with the versionning
+# system of the configuration.
+let
+  nixosReentry = import config.nixos.path {
+    inherit (config.nixos) configuration extraModules;
+    inherit (config.nixpkgs) system;
+    reEnter = true;
+  };
+in
+
+with lib;
+
+{
+  options = {
+    nixos.path = mkOption {
+      default = null;
+      example = literalExample "./nixpkgs-15.09/nixos";
+      type = types.nullOr types.path;
+      description = ''
+        This option give the ability to evaluate the current set of modules
+        with a different version of NixOS. This option can be used version
+        the version of NixOS with the configuration without relying on the
+        <literal>NIX_PATH</literal> environment variable.
+      '';
+    };
+
+    nixos.system = mkOption {
+      example = "i686-linux";
+      type = types.uniq types.str;
+      description = ''
+        Name of the system used to compile NixOS.
+      '';
+    };
+
+    nixos.extraModules = mkOption {
+      default = [];
+      example = literalExample "mkIf config.services.openssh.enable [ ./sshd-config.nix ]";
+      type = types.listOf types.unspecified;
+      description = ''
+        Define additional modules which would be loaded to evaluate the
+        configuration.
+      '';
+    };
+
+    nixos.configuration = mkOption {
+      type = types.unspecified;
+      internal = true;
+      description = ''
+        Option used by <filename>nixos/default.nix</filename> to re-inject
+        the same configuration module as the one used for the current
+        execution.
+      '';
+    };
+
+    nixos.reflect = mkOption {
+      default = { inherit config options; };
+      type = types.unspecified;
+      internal = true;
+      description = ''
+        Provides <literal>config</literal> and <literal>options</literal>
+        computed by the module system and given as argument to all
+        modules. These are used for introspection of options and
+        configuration by tools such as <literal>nixos-option</literal>.
+      '';
+    };
+  };
+
+  config = mkMerge [
+    (mkIf (config.nixos.path != null) (mkForce {
+      system.build.toplevel = nixosReentry.system;
+      system.build.vm = nixosReentry.vm;
+      nixos.reflect = { inherit (nixosReentry) config options; };
+    }))
+
+    { meta.maintainers = singleton lib.maintainers.pierron;
+      meta.doc = ./nixos.xml;
+    }
+  ];
+}
diff --git a/nixos/modules/misc/nixos.xml b/nixos/modules/misc/nixos.xml
new file mode 100644
index 00000000000..f8d3b4bc6e3
--- /dev/null
+++ b/nixos/modules/misc/nixos.xml
@@ -0,0 +1,84 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         version="5.0"
+         xml:id="module-misc-nixos">
+
+<title>NixOS Reentry</title>
+
+<!-- FIXME: render nicely -->
+
+<!-- FIXME: source can be added automatically -->
+<para><emphasis>Source:</emphasis> <filename>modules/misc/nixos.nix</filename></para>
+
+<!-- FIXME: more stuff, like maintainer? -->
+
+<para>NixOS reentry can be used for both pinning the evaluation to a
+specific version of NixOS, and to dynamically add additional modules into
+the Module evaluation.</para>
+
+<section><title>NixOS Version Pinning</title>
+
+<para>To pin a specific version of NixOS, you need a version that you can
+either clone localy, or that you can fetch remotely.</para>
+
+<para>If you already have a cloned version of NixOS in the directory
+<filename>/etc/nixos/nixpkgs-16-03</filename>, then you can specify the
+<option>nixos.path</option> with either the path or the relative path of
+your NixOS clone. For example, you can add the following to your
+<filename>/etc/nixos/configuration.nix</filename> file:
+
+<programlisting>
+nixos.path = ./nixpkgs-16-03/nixos;
+</programlisting>
+</para>
+
+<para>Another option is to fetch a specific version of NixOS, with either
+the <literal>fetchTarball</literal> builtin, or the
+<literal>pkgs.fetchFromGithub</literal> function and use the result as an
+input.
+
+<programlisting>
+nixos.path = "${builtins.fetchTarball https://github.com/NixOS/nixpkgs/archive/1f27976e03c15183191d1b4aa1a40d1f14666cd2.tar.gz}/nixos";
+</programlisting>
+</para>
+
+</section>
+
+
+<section><title>Adding Module Dynamically</title>
+
+<para>To add additional module, the recommended way is to use statically
+known modules in the list of imported arguments as described in <xref
+linkend="sec-modularity" />.  Unfortunately, this recommended method has
+limitation, such that the list of imported files cannot be selected based on
+the content of the configuration.
+
+Fortunately, NixOS reentry system can be used as an alternative to register
+new imported modules based on the content of the configuration. To do so,
+one should define both <option>nixos.path</option> and
+<option>nixos.extraModules</option> options.
+
+<programlisting>
+nixos.path = &lt;nixos&gt;;
+nixos.extraModules =
+  if config.networking.hostName == "server" then
+    [ ./server.nix ] else [ ./client.nix ];
+</programlisting>
+
+Also note, that the above can be reimplemented in a different way which is
+not as expensive, by using <literal>mkIf</literal> at the top each
+configuration if both modules are present on the file system (see <xref
+linkend="sec-option-definitions" />) and by always inmporting both
+modules.</para>
+
+</section>
+
+<section><title>Options</title>
+
+<para>FIXME: auto-generated list of module options.</para>
+
+</section>
+
+
+</chapter>
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 034ea933a7d..242571d41ba 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -52,6 +52,7 @@
   ./misc/lib.nix
   ./misc/locate.nix
   ./misc/meta.nix
+  ./misc/nixos.nix
   ./misc/nixpkgs.nix
   ./misc/passthru.nix
   ./misc/version.nix
diff --git a/nixos/release.nix b/nixos/release.nix
index 1a1ed4bca41..e48954ceaf5 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -276,6 +276,7 @@ in rec {
   tests.networkingProxy = callTest tests/networking-proxy.nix {};
   tests.nfs3 = callTest tests/nfs.nix { version = 3; };
   tests.nfs4 = callTest tests/nfs.nix { version = 4; };
+  tests.nixosPinVersion = callTest tests/nixos-pin-version.nix {};
   tests.nsd = callTest tests/nsd.nix {};
   tests.openssh = callTest tests/openssh.nix {};
   tests.panamax = hydraJob (import tests/panamax.nix { system = "x86_64-linux"; });
diff --git a/nixos/tests/nixos-pin-version.nix b/nixos/tests/nixos-pin-version.nix
new file mode 100644
index 00000000000..91fba2e759d
--- /dev/null
+++ b/nixos/tests/nixos-pin-version.nix
@@ -0,0 +1,57 @@
+{ system ? builtins.currentSystem }:
+
+with import ../lib/testing.nix { inherit system; };
+let
+in
+
+pkgs.stdenv.mkDerivation rec {
+  name = "nixos-pin-version";
+  src = ../..;
+  buildInputs = with pkgs; [ nix gnugrep ];
+
+    withoutPath = pkgs.writeText "configuration.nix" ''
+    {
+      nixos.extraModules = [ ({lib, ...}: { system.nixosRevision = lib.mkForce "ABCDEF"; }) ];
+    }
+  '';
+
+  withPath = pkgs.writeText "configuration.nix" ''
+    {
+      nixos.path = ${src}/nixos ;
+      nixos.extraModules = [ ({lib, ...}: { system.nixosRevision = lib.mkForce "ABCDEF"; }) ];
+    }
+  '';
+
+  phases = "buildPhase";
+  buildPhase = ''
+    datadir="${pkgs.nix}/share"
+    export TEST_ROOT=$(pwd)/test-tmp
+    export NIX_STORE_DIR=$TEST_ROOT/store
+    export NIX_LOCALSTATE_DIR=$TEST_ROOT/var
+    export NIX_LOG_DIR=$TEST_ROOT/var/log/nix
+    export NIX_STATE_DIR=$TEST_ROOT/var/nix
+    export NIX_DB_DIR=$TEST_ROOT/db
+    export NIX_CONF_DIR=$TEST_ROOT/etc
+    export NIX_MANIFESTS_DIR=$TEST_ROOT/var/nix/manifests
+    export NIX_BUILD_HOOK=
+    export PAGER=cat
+    cacheDir=$TEST_ROOT/binary-cache
+    nix-store --init
+
+    export NIX_PATH="nixpkgs=$src:nixos=$src/nixos:nixos-config=${withoutPath}" ;
+    if test $(nix-instantiate $src/nixos -A config.system.nixosRevision --eval-only) != '"ABCDEF"' ; then :;
+    else
+      echo "Unexpected re-entry without the nixos.path option defined.";
+      exit 1;
+    fi;
+
+    export NIX_PATH="nixpkgs=$src:nixos=$src/nixos:nixos-config=${withPath}" ;
+    if test $(nix-instantiate $src/nixos -A config.system.nixosRevision --eval-only) = '"ABCDEF"' ; then :;
+    else
+      echo "Expected a re-entry when the nixos.path option is defined.";
+      exit 1;
+    fi;
+
+    touch $out;
+  '';
+}