Esempio n. 1
0
 def test_nested(self):
     self.assertEquals(py2nix([nix2py("a\nb\nc")], maxwidth=0), "[\n  (a\n  b\n  c)\n]")
     self.assertEquals(
         py2nix({"foo": nix2py("a\nb\nc"), "bar": nix2py("d\ne\nf")}, maxwidth=0),
         # ugly, but probably won't happen in practice
         "{\n  bar = d\n  e\n  f;\n  foo = a\n  b\n  c;\n}",
     )
Esempio n. 2
0
 def test_nested(self):
     self.assertEquals(py2nix([nix2py('a\nb\nc')], maxwidth=0),
                       '[\n  (a\n  b\n  c)\n]')
     self.assertEquals(py2nix({'foo': nix2py('a\nb\nc'),
                               'bar': nix2py('d\ne\nf')}, maxwidth=0),
                       # ugly, but probably won't happen in practice
                       '{\n  bar = d\n  e\n  f;\n  foo = a\n  b\n  c;\n}')
Esempio n. 3
0
 def _eval_flags(self, exprs):
     flags = self._nix_path_flags()
     args = {key: RawValue(val) for key, val in self.args.iteritems()}
     flags.extend(
         ["--arg", "networkExprs", py2nix(exprs, inline=True),
          "--arg", "args", py2nix(args, inline=True),
          "--argstr", "uuid", self.uuid,
          "<nixops/eval-machine-info.nix>"])
     return flags
Esempio n. 4
0
 def _eval_flags(self, exprs):
     flags = self._nix_path_flags()
     args = {key: RawValue(val) for key, val in self.args.iteritems()}
     flags.extend(
         ["--arg", "networkExprs", py2nix(exprs, inline=True),
          "--arg", "args", py2nix(args, inline=True),
          "--argstr", "uuid", self.uuid,
          "<nixops/eval-machine-info.nix>"])
     return flags
Esempio n. 5
0
 def test_nested(self):
     self.assertEqual(
         py2nix([nix2py("a\nb\nc")], maxwidth=0), "[\n  (a\n  b\n  c)\n]"
     )
     self.assertEqual(
         py2nix({"foo": nix2py("a\nb\nc"), "bar": nix2py("d\ne\nf")}, maxwidth=0),
         # ugly, but probably won't happen in practice
         "{\n  bar = d\n  e\n  f;\n  foo = a\n  b\n  c;\n}",
     )
Esempio n. 6
0
 def _eval_flags(self, exprs):
     flags = self._nix_path_flags()
     args = {key: RawValue(val) for key, val in self.args.iteritems()}
     exprs_ = [RawValue(x) if x[0] == '<' else x for x in exprs]
     flags.extend(
         ["--arg", "networkExprs", py2nix(exprs_, inline=True),
          "--arg", "args", py2nix(args, inline=True),
          "--argstr", "uuid", self.uuid,
          "<nixops/eval-deployment.nix>" if self.modular else "<nixops/eval-machine-info.nix>"])
     return flags
Esempio n. 7
0
 def test_nested(self):
     self.assertEquals(py2nix([nix2py('a\nb\nc')], maxwidth=0),
                       '[\n  (a\n  b\n  c)\n]')
     self.assertEquals(
         py2nix({
             'foo': nix2py('a\nb\nc'),
             'bar': nix2py('d\ne\nf')
         },
                maxwidth=0),
         # ugly, but probably won't happen in practice
         '{\n  bar = d\n  e\n  f;\n  foo = a\n  b\n  c;\n}')
Esempio n. 8
0
    def destroy_resources(self, include=[], exclude=[], wipe=False):
        """Destroy all active or obsolete resources."""

        with self._get_deployment_lock():

            def worker(m):
                if not should_do(m, include, exclude): return
                if m.destroy(wipe=wipe): self.delete_resource(m)

            nixops.parallel.run_tasks(nr_workers=-1, tasks=self.resources.values(), worker_fun=worker)

        # Remove the destroyed machines from the rollback profile.
        # This way, a subsequent "nix-env --delete-generations old" or
        # "nix-collect-garbage -d" will get rid of the machine
        # configurations.
        if self.rollback_enabled: # and len(self.active) == 0:
            profile = self.create_profile()
            attrs = {m.name:
                     Function("builtins.storePath", m.cur_toplevel, call=True)
                     for m in self.active.itervalues() if m.cur_toplevel}
            if subprocess.call(
                ["nix-env", "-p", profile, "--set", "*", "-I", "nixops=" + self.expr_path,
                 "-f", "<nixops/update-profile.nix>",
                 "--arg", "machines", py2nix(attrs, inline=True)]) != 0:
                raise Exception("cannot update profile ‘{0}’".format(profile))
Esempio n. 9
0
    def destroy_resources(self, include=[], exclude=[], wipe=False):
        """Destroy all active or obsolete resources."""

        with self._get_deployment_lock():
            for r in self.resources.itervalues():
                r._destroyed_event = threading.Event()
                r._errored = False
                for rev_dep in r.destroy_before(self.resources.itervalues()):
                    try:
                        rev_dep._wait_for.append(r)
                    except AttributeError:
                        rev_dep._wait_for = [ r ]

            def worker(m):
                try:
                    if not should_do(m, include, exclude): return
                    try:
                        for dep in m._wait_for:
                            dep._destroyed_event.wait()
                            # !!! Should we print a message here?
                            if dep._errored:
                                m._errored = True
                                return
                    except AttributeError:
                        pass
                    if m.destroy(wipe=wipe): self.delete_resource(m)
                except:
                    m._errored = True
                    raise
                finally:
                    m._destroyed_event.set()

            nixops.parallel.run_tasks(nr_workers=-1, tasks=self.resources.values(), worker_fun=worker)

        # Remove the destroyed machines from the rollback profile.
        # This way, a subsequent "nix-env --delete-generations old" or
        # "nix-collect-garbage -d" will get rid of the machine
        # configurations.
        if self.rollback_enabled: # and len(self.active) == 0:
            profile = self.create_profile()
            attrs = {m.name:
                     Function("builtins.storePath", m.cur_toplevel, call=True)
                     for m in self.active.itervalues() if m.cur_toplevel}
            if subprocess.call(
                ["nix-env", "-p", profile, "--set", "*", "-I", "nixops=" + self.expr_path,
                 "-f", "<nixops/update-profile.nix>",
                 "--arg", "machines", py2nix(attrs, inline=True)]) != 0:
                raise Exception("cannot update profile ‘{0}’".format(profile))
Esempio n. 10
0
    def destroy_resources(self, include=[], exclude=[], wipe=False):
        """Destroy all active and obsolete resources."""

        with self._get_deployment_lock():
            self._destroy_resources(include, exclude, wipe)

        # Remove the destroyed machines from the rollback profile.
        # This way, a subsequent "nix-env --delete-generations old" or
        # "nix-collect-garbage -d" will get rid of the machine
        # configurations.
        if self.rollback_enabled: # and len(self.active) == 0:
            profile = self.create_profile()
            attrs = {m.name:
                     Call(RawValue("builtins.storePath"), m.cur_toplevel)
                     for m in self.active.itervalues() if m.cur_toplevel}
            if subprocess.call(
                ["nix-env", "-p", profile, "--set", "*", "-I", "nixops=" + self.expr_path,
                 "-f", "<nixops/update-profile.nix>",
                 "--arg", "machines", py2nix(attrs, inline=True)]) != 0:
                raise Exception("cannot update profile ‘{0}’".format(profile))
Esempio n. 11
0
    def get_physical_spec(self):
        """Compute the contents of the Nix expression specifying the computed physical deployment attributes"""

        active_machines = self.active
        active_resources = self.active_resources

        attrs_per_resource = {m.name: [] for m in active_resources.itervalues()}
        authorized_keys = {m.name: [] for m in active_machines.itervalues()}
        kernel_modules = {m.name: set() for m in active_machines.itervalues()}
        trusted_interfaces = {m.name: set() for m in active_machines.itervalues()}

        # Hostnames should be accumulated like this:
        #
        #   hosts[local_name][remote_ip] = [name1, name2, ...]
        #
        # This makes hosts deterministic and is more in accordance to the
        # format in hosts(5), which is like this:
        #
        #   ip_address canonical_hostname [aliases...]
        #
        # This is critical for example when using host names for access
        # control, because the canonical_hostname is returned in reverse
        # lookups.
        hosts = defaultdict(lambda: defaultdict(list))

        for m in active_machines.itervalues():
            for m2 in active_machines.itervalues():
                ip = m.address_to(m2)
                if ip:
                    hosts[m.name][ip] += [m2.name, m2.name + "-unencrypted"]
            # Always use the encrypted/unencrypted suffixes for aliases rather
            # than for the canonical name!
            hosts[m.name]["127.0.0.1"].append(m.name + "-encrypted")

        def index_to_private_ip(index):
            n = 105 + index / 256
            assert n <= 255
            return "192.168.{0}.{1}".format(n, index % 256)

        def do_machine(m):
            defn = self.definitions[m.name]
            attrs_list = attrs_per_resource[m.name]

            # Emit configuration to realise encrypted peer-to-peer links.
            for m2_name in defn.encrypted_links_to:

                if m2_name not in active_machines:
                    raise Exception("‘deployment.encryptedLinksTo’ in machine ‘{0}’ refers to an unknown machine ‘{1}’"
                                    .format(m.name, m2_name))
                m2 = active_machines[m2_name]
                # Don't create two tunnels between a pair of machines.
                if m.name in self.definitions[m2.name].encrypted_links_to and m.name >= m2.name:
                    continue
                local_ipv4 = index_to_private_ip(m.index)
                remote_ipv4 = index_to_private_ip(m2.index)
                local_tunnel = 10000 + m2.index
                remote_tunnel = 10000 + m.index
                attrs_list.append({
                    ('networking', 'p2pTunnels', 'ssh', m2.name): {
                        'target': '{0}-unencrypted'.format(m2.name),
                        'localTunnel': local_tunnel,
                        'remoteTunnel': remote_tunnel,
                        'localIPv4': local_ipv4,
                        'remoteIPv4': remote_ipv4,
                        'privateKey': '/root/.ssh/id_charon_vpn',
                    }
                })

                # FIXME: set up the authorized_key file such that ‘m’
                # can do nothing more than create a tunnel.
                authorized_keys[m2.name].append(m.public_vpn_key)
                kernel_modules[m.name].add('tun')
                kernel_modules[m2.name].add('tun')
                hosts[m.name][remote_ipv4] += [m2.name, m2.name + "-encrypted"]
                hosts[m2.name][local_ipv4] += [m.name, m.name + "-encrypted"]
                trusted_interfaces[m.name].add('tun' + str(local_tunnel))
                trusted_interfaces[m2.name].add('tun' + str(remote_tunnel))

            private_ipv4 = m.private_ipv4
            if private_ipv4:
                attrs_list.append({
                    ('networking', 'privateIPv4'): private_ipv4
                })
            public_ipv4 = m.public_ipv4
            if public_ipv4:
                attrs_list.append({
                    ('networking', 'publicIPv4'): public_ipv4
                })

            if self.nixos_version_suffix:
                attrs_list.append({
                    ('system', 'nixosVersionSuffix'): self.nixos_version_suffix
                })

        for m in active_machines.itervalues():
            do_machine(m)

        def emit_resource(r):
            config = []
            config.extend(attrs_per_resource[r.name])
            if is_machine(r):
                # Sort the hosts by its canonical host names.
                sorted_hosts = sorted(hosts[r.name].iteritems(),
                                      key=lambda item: item[1][0])
                # Just to remember the format:
                #   ip_address canonical_hostname [aliases...]
                extra_hosts = ["{0} {1}".format(ip, ' '.join(names))
                               for ip, names in sorted_hosts]

                if authorized_keys[r.name]:
                    config.append({
                        ('users', 'extraUsers', 'root'): {
                            ('openssh', 'authorizedKeys', 'keys'): authorized_keys[r.name]
                        },
                        ('services', 'openssh'): {
                            'extraConfig': "PermitTunnel yes\n"
                        },
                    })

                config.append({
                    ('boot', 'kernelModules'): list(kernel_modules[r.name]),
                    ('networking', 'firewall'): {
                        'trustedInterfaces': list(trusted_interfaces[r.name])
                    },
                    ('networking', 'extraHosts'): '\n'.join(extra_hosts) + "\n"
                })


                # Add SSH public host keys for all machines in network  
                for m2 in active_machines.itervalues():
                    if hasattr(m2, 'public_host_key') and m2.public_host_key:
                        # Using references to files in same tempdir for now, until NixOS has support
                        # for adding the keys directly as string. This way at least it is compatible
                        # with older versions of NixOS as well.
                        # TODO: after reasonable amount of time replace with string option
                        config.append({
                            ('services', 'openssh', 'knownHosts', m2.name): {
                                 'hostNames': [m2.name + "-unencrypted",
                                               m2.name + "-encrypted",
                                               m2.name],
                                 'publicKeyFile': RawValue(
                                      "./{0}.public_host_key".format(m2.name)
                                 ),
                            }
                        })

            merged = reduce(nixmerge, config) if len(config) > 0 else {}
            physical = r.get_physical_spec()

            if len(merged) == 0 and len(physical) == 0:
                return {}
            else:
                return r.prefix_definition({
                    r.name: Function("{ config, pkgs, ... }", {
                        'config': merged,
                        'imports': [physical],
                    })
                })

        return py2nix(reduce(nixmerge, [
            emit_resource(r) for r in active_resources.itervalues()
        ])) + "\n"
Esempio n. 12
0
 def set_argstr(self, name, value):
     """Set a persistent argument to the deployment specification."""
     assert isinstance(value, basestring)
     self.set_arg(name, py2nix(value, inline=True))
Esempio n. 13
0
 def assert_nix(self, nix_expr, expected, maxwidth=80, inline=False):
     result = py2nix(nix_expr, maxwidth=maxwidth, inline=inline)
     self.assertEqual(result, expected, "Expected:\n{0}\nGot:\n{1}".format(expected, result))
Esempio n. 14
0
 def test_simple(self):
     self.assertEquals(py2nix(nix2py("{\na = b;\n}"), maxwidth=0), "{\na = b;\n}")
     self.assertEquals(py2nix(nix2py("\n{\na = b;\n}\n"), maxwidth=0), "{\na = b;\n}")
Esempio n. 15
0
def print_physical_backup_spec(backupid):
    depl = open_deployment(args)
    config = {}
    for m in depl.active.itervalues():
        config[m.name] = m.get_physical_backup_spec(backupid)
    sys.stdout.write(py2nix(config))
Esempio n. 16
0
          gatewayId = resources.vpcInternetGateways.igw-test;
        };

      vpcInternetGateways.igw-test =
        { resources, ... }:
        {
          inherit region;
          vpcId = resources.vpc.vpc-test;
        };
    };
  }
  """)

CFG_DNS_SUPPORT = ("enable_dns_support.nix",
                   py2nix({
                       ('resources', 'vpc', 'vpc-test', 'enableDnsSupport'):
                       True
                   }))

CFG_IPV6 = (
    "ipv6.nix",
    py2nix({
        ('resources', 'vpc', 'vpc-test', 'amazonProvidedIpv6CidrBlock'):
        True
    }))

CFG_NAT_GTW = ("nat_gtw.nix", """
   {
      resources.elasticIPs.nat-eip =
      {
        region = "us-east-1";
        vpc = true;
Esempio n. 17
0
    def get_physical_spec(self):
        """Compute the contents of the Nix expression specifying the computed physical deployment attributes"""

        active_machines = self.active
        active_resources = self.active_resources

        attrs_per_resource = {m.name: [] for m in active_resources.itervalues()}
        authorized_keys = {m.name: [] for m in active_machines.itervalues()}
        kernel_modules = {m.name: set() for m in active_machines.itervalues()}
        trusted_interfaces = {m.name: set() for m in active_machines.itervalues()}

        # Hostnames should be accumulated like this:
        #
        #   hosts[local_name][remote_ip] = [name1, name2, ...]
        #
        # This makes hosts deterministic and is more in accordance to the
        # format in hosts(5), which is like this:
        #
        #   ip_address canonical_hostname [aliases...]
        #
        # This is critical for example when using host names for access
        # control, because the canonical_hostname is returned in reverse
        # lookups.
        hosts = defaultdict(lambda: defaultdict(list))

        def index_to_private_ip(index):
            n = 105 + index / 256
            assert n <= 255
            return "192.168.{0}.{1}".format(n, index % 256)

        def do_machine(m):
            defn = self.definitions[m.name]
            attrs_list = attrs_per_resource[m.name]

            # Emit configuration to realise encrypted peer-to-peer links.
            for m2 in active_resources.itervalues():
                ip = m.address_to(m2)
                if ip:
                    hosts[m.name][ip] += [m2.name, m2.name + "-unencrypted"]

            # Always use the encrypted/unencrypted suffixes for aliases rather
            # than for the canonical name!
            hosts[m.name]["127.0.0.1"].append(m.name + "-encrypted")

            for m2_name in defn.encrypted_links_to:

                if m2_name not in active_machines:
                    raise Exception(
                        "‘deployment.encryptedLinksTo’ in machine ‘{0}’ refers to an unknown machine ‘{1}’".format(
                            m.name, m2_name
                        )
                    )
                m2 = active_machines[m2_name]

                # Don't create two tunnels between a pair of machines.
                if m.name in self.definitions[m2.name].encrypted_links_to and m.name >= m2.name:
                    continue
                local_ipv4 = index_to_private_ip(m.index)
                remote_ipv4 = index_to_private_ip(m2.index)
                local_tunnel = 10000 + m2.index
                remote_tunnel = 10000 + m.index
                attrs_list.append(
                    {
                        ("networking", "p2pTunnels", "ssh", m2.name): {
                            "target": "{0}-unencrypted".format(m2.name),
                            "targetPort": m2.ssh_port,
                            "localTunnel": local_tunnel,
                            "remoteTunnel": remote_tunnel,
                            "localIPv4": local_ipv4,
                            "remoteIPv4": remote_ipv4,
                            "privateKey": "/root/.ssh/id_charon_vpn",
                        }
                    }
                )

                # FIXME: set up the authorized_key file such that ‘m’
                # can do nothing more than create a tunnel.
                authorized_keys[m2.name].append(m.public_vpn_key)
                kernel_modules[m.name].add("tun")
                kernel_modules[m2.name].add("tun")
                hosts[m.name][remote_ipv4] += [m2.name, m2.name + "-encrypted"]
                hosts[m2.name][local_ipv4] += [m.name, m.name + "-encrypted"]
                trusted_interfaces[m.name].add("tun" + str(local_tunnel))
                trusted_interfaces[m2.name].add("tun" + str(remote_tunnel))

            private_ipv4 = m.private_ipv4
            if private_ipv4:
                attrs_list.append({("networking", "privateIPv4"): private_ipv4})
            public_ipv4 = m.public_ipv4
            if public_ipv4:
                attrs_list.append({("networking", "publicIPv4"): public_ipv4})
            public_vpn_key = m.public_vpn_key
            if public_vpn_key:
                attrs_list.append({("networking", "vpnPublicKey"): public_vpn_key})

            # Set system.stateVersion if the Nixpkgs version supports it.
            if nixops.util.parse_nixos_version(defn.config["nixosVersion"]) >= ["15", "09"]:
                attrs_list.append(
                    {("system", "stateVersion"): Call(RawValue("lib.mkDefault"), m.state_version or "14.12")}
                )

            if self.nixos_version_suffix:
                attrs_list.append({("system", "nixosVersionSuffix"): self.nixos_version_suffix})

        for m in active_machines.itervalues():
            do_machine(m)

        def emit_resource(r):
            config = []
            config.extend(attrs_per_resource[r.name])
            if is_machine(r):
                # Sort the hosts by its canonical host names.
                sorted_hosts = sorted(hosts[r.name].iteritems(), key=lambda item: item[1][0])
                # Just to remember the format:
                #   ip_address canonical_hostname [aliases...]
                extra_hosts = ["{0} {1}".format(ip, " ".join(names)) for ip, names in sorted_hosts]

                if authorized_keys[r.name]:
                    config.append(
                        {
                            ("users", "extraUsers", "root"): {
                                ("openssh", "authorizedKeys", "keys"): authorized_keys[r.name]
                            },
                            ("services", "openssh"): {"extraConfig": "PermitTunnel yes\n"},
                        }
                    )

                config.append(
                    {
                        ("boot", "kernelModules"): list(kernel_modules[r.name]),
                        ("networking", "firewall"): {"trustedInterfaces": list(trusted_interfaces[r.name])},
                        ("networking", "extraHosts"): "\n".join(extra_hosts) + "\n",
                    }
                )

                # Add SSH public host keys for all machines in network.
                for m2 in active_machines.itervalues():
                    if hasattr(m2, "public_host_key") and m2.public_host_key:
                        # Using references to files in same tempdir for now, until NixOS has support
                        # for adding the keys directly as string. This way at least it is compatible
                        # with older versions of NixOS as well.
                        # TODO: after reasonable amount of time replace with string option
                        config.append(
                            {
                                ("services", "openssh", "knownHosts", m2.name): {
                                    "hostNames": [m2.name + "-unencrypted", m2.name + "-encrypted", m2.name],
                                    "publicKey": m2.public_host_key,
                                }
                            }
                        )

            merged = reduce(nixmerge, config) if len(config) > 0 else {}
            physical = r.get_physical_spec()

            if len(merged) == 0 and len(physical) == 0:
                return {}
            else:
                return r.prefix_definition(
                    {r.name: Function("{ config, lib, pkgs, ... }", {"config": merged, "imports": [physical]})}
                )

        return py2nix(reduce(nixmerge, [emit_resource(r) for r in active_resources.itervalues()], {})) + "\n"
Esempio n. 18
0
 def test_simple(self):
     self.assertEquals(py2nix(nix2py('{\na = b;\n}'), maxwidth=0),
                       '{\na = b;\n}')
     self.assertEquals(py2nix(nix2py('\n{\na = b;\n}\n'), maxwidth=0),
                       '{\na = b;\n}')
Esempio n. 19
0
    def build_configs(self, include, exclude, dry_run=False, repair=False):
        """Build the machine configurations in the Nix store."""

        def write_temp_file(tmpfile, contents):
            f = open(tmpfile, "w")
            f.write(contents)
            f.close()

        self.logger.log("building all machine configurations...")

        # Set the NixOS version suffix, if we're building from Git.
        # That way ‘nixos-version’ will show something useful on the
        # target machines.
        nixos_path = subprocess.check_output(
            ["nix-instantiate", "--find-file", "nixpkgs/nixos"] + self._nix_path_flags()).rstrip()
        get_version_script = nixos_path + "/modules/installer/tools/get-version-suffix"
        if os.path.exists(nixos_path + "/.git") and os.path.exists(get_version_script):
            self.nixos_version_suffix = subprocess.check_output(["/bin/sh", get_version_script] + self._nix_path_flags()).rstrip()

        phys_expr = self.tempdir + "/physical.nix"
        p = self.get_physical_spec()
        write_temp_file(phys_expr, p)
        if debug: print >> sys.stderr, "generated physical spec:\n" + p

        for m in self.active.itervalues():
            if hasattr(m, "public_host_key") and m.public_host_key: # FIXME: use a method in MachineState.
                write_temp_file("{0}/{1}.public_host_key".format(self.tempdir, m.name), m.public_host_key + "\n")

        selected = [m for m in self.active.itervalues() if should_do(m, include, exclude)]

        names = map(lambda m: m.name, selected)

        # If we're not running on Linux, then perform the build on the
        # target machines.  FIXME: Also enable this if we're on 32-bit
        # and want to deploy to 64-bit.
        if platform.system() != 'Linux' and os.environ.get('NIX_REMOTE') != 'daemon':
            remote_machines = []
            for m in sorted(selected, key=lambda m: m.index):
                key_file = m.get_ssh_private_key_file()
                if not key_file: raise Exception("do not know private SSH key for machine ‘{0}’".format(m.name))
                # FIXME: Figure out the correct machine type of ‘m’ (it might not be x86_64-linux).
                remote_machines.append("root@{0} {1} {2} 2 1\n".format(m.get_ssh_name(), 'i686-linux,x86_64-linux', key_file))
                # Use only a single machine for now (issue #103).
                break
            remote_machines_file = "{0}/nix.machines".format(self.tempdir)
            with open(remote_machines_file, "w") as f:
                f.write("".join(remote_machines))
            os.environ['NIX_REMOTE_SYSTEMS'] = remote_machines_file

            # FIXME: Use ‘--option use-build-hook true’ instead of setting
            # $NIX_BUILD_HOOK, once Nix supports that.
            os.environ['NIX_BUILD_HOOK'] = os.path.dirname(os.path.realpath(nixops.util.which("nix-build"))) + "/../libexec/nix/build-remote.pl"

            load_dir = "{0}/current-load".format(self.tempdir)
            if not os.path.exists(load_dir): os.makedirs(load_dir, 0700)
            os.environ['NIX_CURRENT_LOAD'] = load_dir

        try:
            configs_path = subprocess.check_output(
                ["nix-build"]
                + self._eval_flags(self.nix_exprs + [phys_expr]) +
                ["--arg", "names", py2nix(names, inline=True),
                 "-A", "machines", "-o", self.tempdir + "/configs"]
                + (["--dry-run"] if dry_run else [])
                + (["--repair"] if repair else []),
                stderr=self.logger.log_file).rstrip()
        except subprocess.CalledProcessError:
            raise Exception("unable to build all machine configurations")

        if self.rollback_enabled:
            profile = self.create_profile()
            if subprocess.call(["nix-env", "-p", profile, "--set", configs_path]) != 0:
                raise Exception("cannot update profile ‘{0}’".format(profile))

        return configs_path
Esempio n. 20
0
 def test_simple(self):
     self.assertEquals(py2nix(nix2py('{\na = b;\n}'), maxwidth=0),
                       '{\na = b;\n}')
     self.assertEquals(py2nix(nix2py('\n{\na = b;\n}\n'), maxwidth=0),
                       '{\na = b;\n}')
Esempio n. 21
0
def eval(
    # eval-machine-info args
    networkExpr: NetworkFile,  # Flake conditional
    uuid: str,
    deploymentName: str,
    networkExprs: List[str] = [],
    args: Dict[str, str] = {},
    pluginNixExprs: List[str] = [],
    checkConfigurationOptions: bool = True,
    # Extend internal defaults
    nix_path: List[str] = [],
    # nix-instantiate args
    nix_args: Dict[str, Any] = {},
    attr: Optional[str] = None,
    extra_flags: List[str] = [],
    # Non-propagated args
    stderr: Optional[TextIO] = None,
) -> Any:

    exprs: List[str] = list(networkExprs)
    if not networkExpr.is_flake:
        exprs.append(networkExpr.network)

    argv: List[str] = (
        [
            "nix-instantiate", "--eval-only", "--json", "--strict",
            "--show-trace"
        ] + [os.path.join(get_expr_path(), "eval-machine-info.nix")] +
        ["-I", "nixops=" + get_expr_path()] + [
            "--arg",
            "networkExprs",
            py2nix([RawValue(x) if x[0] == "<" else x for x in exprs]),
        ] + [
            "--arg",
            "args",
            py2nix({key: RawValue(val)
                    for key, val in args.items()},
                   inline=True),
        ] + ["--argstr", "uuid", uuid] +
        ["--argstr", "deploymentName", deploymentName] +
        ["--arg", "pluginNixExprs",
         py2nix(pluginNixExprs)] + [
             "--arg", "checkConfigurationOptions",
             json.dumps(checkConfigurationOptions)
         ] +
        list(itertools.chain(*[["-I", x]
                               for x in (nix_path + pluginNixExprs)])) +
        extra_flags)

    for k, v in nix_args.items():
        argv.extend(["--arg", k, py2nix(v, inline=True)])

    if attr:
        argv.extend(["-A", attr])

    if networkExpr.is_flake:
        argv.extend(["--allowed-uris", get_expr_path()])
        argv.extend(["--argstr", "flakeUri", networkExpr.network])

    try:
        ret = subprocess.check_output(argv, stderr=stderr, text=True)
        return json.loads(ret)
    except OSError as e:
        raise Exception("unable to run ‘nix-instantiate’: {0}".format(e))
    except subprocess.CalledProcessError:
        raise NixEvalError
Esempio n. 22
0
          destinationCidrBlock = "0.0.0.0/0";
          gatewayId = resources.vpcInternetGateways.igw-test;
        };

      vpcInternetGateways.igw-test =
        { resources, ... }:
        {
          inherit region;
          vpcId = resources.vpc.vpc-test;
        };
    };
  }
  """)

CFG_DNS_SUPPORT = ("enable_dns_support.nix", py2nix({
    ('resources', 'vpc', 'vpc-test', 'enableDnsSupport'): True
    }))

CFG_IPV6 = ("ipv6.nix", py2nix({
    ('resources', 'vpc', 'vpc-test', 'amazonProvidedIpv6CidrBlock'): True
    }))

CFG_NAT_GTW = ("nat_gtw.nix", """
   {
      resources.elasticIPs.nat-eip =
      {
        region = "us-east-1";
        vpc = true;
      };

      resources.vpcNatGateways.nat =