Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: NixOS/nixops
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 4c7acbbc006b
Choose a base ref
...
head repository: NixOS/nixops
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: eb51bdabb374
Choose a head ref
  • 1 commit
  • 4 files changed
  • 1 contributor

Commits on Oct 4, 2019

  1. Support deploying from a flake

    Example usage:
    
      $ nixops create -d hydra-ec2-demo --flake github:edolstra/hydra-ec2-demo
      $ nixops deploy
    
    to get an EC2 instance running Hydra.
    
    Evaluation currently doesn't use pure mode because we need access to
    NixOps's NixOS modules, and to physical.nix.
    edolstra committed Oct 4, 2019

    Verified

    This commit was signed with the committer’s verified signature.
    tadeokondrak Tadeo Kondrak
    Copy the full SHA
    eb51bda View commit details
Showing with 72 additions and 12 deletions.
  1. +17 −4 nix/eval-machine-info.nix
  2. +3 −0 nixops/backends/__init__.py
  3. +27 −1 nixops/deployment.py
  4. +25 −7 nixops/script_defs.py
21 changes: 17 additions & 4 deletions nix/eval-machine-info.nix
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
{ system ? builtins.currentSystem
, networkExprs
, flakeUri ? null
, checkConfigurationOptions ? true
, uuid
, deploymentName
, args
, pluginNixExprs
}:

# FIXME: don't rely on <nixpkgs>.
with import <nixpkgs> { inherit system; };
with lib;

@@ -31,14 +33,25 @@ rec {
startSet = map exprToKey networkExprs;
operator = { key }: map exprToKey ((getNetworkFromExpr key).require or []);
};
in map ({ key }: getNetworkFromExpr key) networkExprClosure;
in
map ({ key }: getNetworkFromExpr key) networkExprClosure
++ optional (flakeUri != null)
((call (builtins.getFlake flakeUri).outputs.nixopsConfigurations.default) // { _file = "<${flakeUri}>"; });

call = x: if builtins.isFunction x then x args else x;

network = zipAttrs networks;

defaults = network.defaults or [];

evalConfig =
if flakeUri != null
then
if network ? nixpkgs
then (head (network.nixpkgs)).lib.nixosSystem
else throw "NixOps network must have a 'nixpkgs' attribute"
else import "<nixpkgs/nixos/lib/eval-config.nix>";

# Compute the definitions of the machines.
nodes =
listToAttrs (map (machineName:
@@ -52,14 +65,14 @@ rec {
networks;
in
{ name = machineName;
value = import <nixpkgs/nixos/lib/eval-config.nix> {
value = evalConfig {
modules =
modules ++
defaults ++
[ deploymentInfoModule ] ++
[ { key = "nixops-stuff";
# Make NixOps's deployment.* options available.
imports = [ ./options.nix ./resource.nix pluginOptions ];
imports = [ ./options.nix ./resource.nix pluginOptions ];
# Provide a default hostname and deployment target equal
# to the attribute name of the machine in the model.
networking.hostName = mkOverride 900 machineName;
@@ -70,7 +83,7 @@ rec {
extraArgs = { inherit nodes resources uuid deploymentName; name = machineName; };
};
}
) (attrNames (removeAttrs network [ "network" "defaults" "resources" "require" "_file" ])));
) (attrNames (removeAttrs network [ "network" "defaults" "resources" "require" "nixpkgs" "_file" ])));

# Compute the definitions of the non-machine resources.
resourcesByType = zipAttrs (network.resources or []);
3 changes: 3 additions & 0 deletions nixops/backends/__init__.py
Original file line number Diff line number Diff line change
@@ -58,6 +58,9 @@ class MachineState(nixops.resources.ResourceState):
# this machine.
cur_toplevel = nixops.util.attr_property("toplevel", None)

# Immutable flake URI from which this machine was built.
cur_flake_uri = nixops.util.attr_property("curFlakeUri", None)

# Time (in Unix epoch) the instance was started, if known.
start_time = nixops.util.attr_property("startTime", None, int)

28 changes: 27 additions & 1 deletion nixops/deployment.py
Original file line number Diff line number Diff line change
@@ -47,6 +47,8 @@ class Deployment(object):
name = nixops.util.attr_property("name", None)
nix_exprs = nixops.util.attr_property("nixExprs", [], 'json')
nix_path = nixops.util.attr_property("nixPath", [], 'json')
flake_uri = nixops.util.attr_property("flakeUri", None)
cur_flake_uri = nixops.util.attr_property("curFlakeUri", None)
args = nixops.util.attr_property("args", {}, 'json')
description = nixops.util.attr_property("description", default_description)
configs_path = nixops.util.attr_property("configsPath", None)
@@ -88,6 +90,8 @@ def __init__(self, statefile, uuid, log_file=sys.stderr):

self.definitions = None

self._cur_flake_uri = None


@property
def tempdir(self):
@@ -260,6 +264,16 @@ def _nix_path_flags(self):
return flags


def _get_cur_flake_uri(self):
assert self.flake_uri is not None
if self._cur_flake_uri is None:
out = json.loads(subprocess.check_output(
["nix", "flake", "info", "--json", "--", self.flake_uri],
stderr=self.logger.log_file))
self._cur_flake_uri = out['uri']
return self._cur_flake_uri


def _eval_flags(self, exprs):
flags = self._nix_path_flags()
args = {key: RawValue(val) for key, val in self.args.iteritems()}
@@ -275,7 +289,14 @@ def _eval_flags(self, exprs):
"--argstr", "uuid", self.uuid,
"--argstr", "deploymentName", self.name if self.name else "",
"--arg", "pluginNixExprs", py2nix(extraexprs),
"<nixops/eval-machine-info.nix>"])
self.expr_path + "/eval-machine-info.nix"])

if self.flake_uri is not None:
flags.extend(
[#"--pure-eval", # FIXME
"--argstr", "flakeUri", self._get_cur_flake_uri(),
"--allowed-uris", self.expr_path])

return flags


@@ -762,6 +783,7 @@ def worker(m):
# configuration.
m.cur_configs_path = configs_path
m.cur_toplevel = m.new_toplevel
m.cur_flake_uri = self._get_cur_flake_uri() if self.flake_uri is not None else None

except Exception as e:
# This thread shouldn't throw an exception because
@@ -1023,6 +1045,8 @@ def worker(r):

if dry_activate: return

self.cur_flake_uri = self._get_cur_flake_uri() if self.flake_uri is not None else None

# Trigger cleanup of resources, e.g. disks that need to be detached etc. Needs to be
# done after activation to make sure they are not in use anymore.
def cleanup_worker(r):
@@ -1101,6 +1125,8 @@ def _rollback(self, generation, include=[], exclude=[], check=False,
sync=sync, always_activate=True,
dry_activate=False, max_concurrent_activate=max_concurrent_activate)

self.cur_flake_uri = None


def rollback(self, **kwargs):
with self._get_deployment_lock():
32 changes: 25 additions & 7 deletions nixops/script_defs.py
Original file line number Diff line number Diff line change
@@ -110,11 +110,23 @@ def set_name(depl, name):
def modify_deployment(args, depl):
nix_exprs = args.nix_exprs
templates = args.templates or []
for i in templates: nix_exprs.append("<nixops/templates/{0}.nix>".format(i))
if len(nix_exprs) == 0:
raise Exception("you must specify the path to a Nix expression and/or use ‘-t’")
depl.nix_exprs = [os.path.abspath(x) if x[0:1] != '<' else x for x in nix_exprs]
depl.nix_path = [nixops.util.abs_nix_path(x) for x in sum(args.nix_path or [], [])]
if args.flake is None:
for i in templates: nix_exprs.append("<nixops/templates/{0}.nix>".format(i))
if len(nix_exprs) == 0:
raise Exception("you must specify the path to a Nix expression and/or use ‘-t’")
depl.nix_exprs = [os.path.abspath(x) if x[0:1] != '<' else x for x in nix_exprs]
depl.nix_path = [nixops.util.abs_nix_path(x) for x in sum(args.nix_path or [], [])]
else:
if len(nix_exprs):
raise Exception("you cannot specify a Nix expression in conjunction with '--flake'")
if args.nix_path:
raise Exception("you cannot specify a Nix search path ('-I') in conjunction with '--flake'")
if len(templates) != 0:
raise Exception("you cannot specify a template ('-t') in conjunction with '--flake'")
# FIXME: should absolutize args.flake if it's a local path.
depl.flake_uri = args.flake
depl.nix_exprs = []
depl.nix_path = []


def op_create(args):
@@ -229,8 +241,13 @@ def name_to_key(name):
print "Network name:", depl.name or "(none)"
print "Network UUID:", depl.uuid
print "Network description:", depl.description
print "Nix expressions:", " ".join(depl.nix_exprs)
if depl.nix_path != []: print "Nix path:", " ".join(map(lambda x: "-I " + x, depl.nix_path))
if depl.flake_uri is None:
print "Nix expressions:", " ".join(depl.nix_exprs)
if depl.nix_path != []: print "Nix path:", " ".join(map(lambda x: "-I " + x, depl.nix_path))
else:
print "Flake URI:", depl.flake_uri
if depl.cur_flake_uri is not None:
print "Deployed flake URI:", depl.cur_flake_uri
if depl.rollback_enabled: print "Nix profile:", depl.get_profile()
if depl.args != {}: print "Nix arguments:", ", ".join([n + " = " + v for n, v in depl.args.iteritems()])
print
@@ -777,6 +794,7 @@ def add_subparser(subparsers, name, help):
def add_common_modify_options(subparser):
subparser.add_argument('nix_exprs', nargs='*', metavar='NIX-FILE', help='Nix expression(s) defining the network')
subparser.add_argument('--template', '-t', action="append", dest="templates", metavar='TEMPLATE', help='name of template to be used')
subparser.add_argument('--flake', dest="flake", metavar='FLAKE_URI', help='URI of the flake that defines the network')


def add_common_deployment_options(subparser):