]> git.ipfire.org Git - location/libloc.git/commitdiff
export: Allow exporting to stdout
authorMichael Tremer <michael.tremer@ipfire.org>
Wed, 2 Mar 2022 10:53:04 +0000 (10:53 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Wed, 2 Mar 2022 10:53:04 +0000 (10:53 +0000)
This is useful if you want to pipe output straight into another program.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
man/location.txt
src/python/export.py
src/python/location.in

index c3abff1e4ddd8bc1eae6919fe0dce0c7bb2e5949..3dfddf511acce35869123a8efecf1b8ad180abd7 100644 (file)
@@ -39,7 +39,7 @@ or countries.
 
 == COMMANDS
 
-'export --directory=DIR [--format=FORMAT] [--family=ipv6|ipv4] [ASN|CC ...]'::
+'export [--directory=DIR] [--format=FORMAT] [--family=ipv6|ipv4] [ASN|CC ...]'::
        This command exports the whole database into the given directory.
        +
        The output can be filtered by only exporting a certain address family, or by passing
@@ -47,6 +47,9 @@ or countries.
        +
        The output format can be chosen with the '--format' parameter. For possible formats,
        please see below.
+       +
+       If the '--directory' option is omitted, the output will be written to stdout which
+       is useful when you want to load any custom exports straight into nftables or ipset.
 
 'get-as ASN [ASN...]'::
        This command returns the name of the owning organisation of the Autonomous
index c5d7475408c18474e58d065691642eabeed413ec..1c6743c205ab33df094de07f06dd2aebf634503e 100644 (file)
@@ -23,7 +23,9 @@ import logging
 import math
 import os
 import socket
+import sys
 
+from .i18n import _
 import _location
 
 # Initialise logging
@@ -66,7 +68,12 @@ class OutputWriter(object):
                """
                        Convenience function to open a file
                """
-               f = open(filename, cls.mode)
+               if filename:
+                       f = open(filename, cls.mode)
+               elif "b" in cls.mode:
+                       f = io.BytesIO()
+               else:
+                       f = io.StringIO()
 
                return cls(f, *args, **kwargs)
 
@@ -94,8 +101,22 @@ class OutputWriter(object):
                """
                self._write_footer()
 
-               # Close the file
-               self.f.close()
+               # Flush all output
+               self.f.flush()
+
+       def print(self):
+               """
+                       Prints the entire output line by line
+               """
+               if isinstance(self.f, io.BytesIO):
+                       raise TypeError(_("Won't write binary output to stdout"))
+
+               # Go back to the beginning
+               self.f.seek(0)
+
+               # Iterate over everything line by line
+               for line in self.f:
+                       sys.stdout.write(line)
 
 
 class IpsetOutputWriter(OutputWriter):
@@ -199,6 +220,8 @@ class Exporter(object):
                self.db, self.writer = db, writer
 
        def export(self, directory, families, countries, asns):
+               filename = None
+
                for family in families:
                        log.debug("Exporting family %s" % family)
 
@@ -206,17 +229,25 @@ class Exporter(object):
 
                        # Create writers for countries
                        for country_code in countries:
-                               filename = self._make_filename(
-                                       directory, prefix=country_code, suffix=self.writer.suffix, family=family,
-                               )
+                               if directory:
+                                       filename = self._make_filename(
+                                               directory,
+                                               prefix=country_code,
+                                               suffix=self.writer.suffix,
+                                               family=family,
+                                       )
 
-                               writers[country_code] = self.writer.open(filename, family, prefix="%s" % country_code)
+                               writers[country_code] = self.writer.open(filename, family, prefix=country_code)
 
                        # Create writers for ASNs
                        for asn in asns:
-                               filename = self._make_filename(
-                                       directory, "AS%s" % asn, suffix=self.writer.suffix, family=family,
-                               )
+                               if directory:
+                                       filename = self._make_filename(
+                                               directory,
+                                               prefix="AS%s" % asn,
+                                               suffix=self.writer.suffix,
+                                               family=family,
+                                       )
 
                                writers[asn] = self.writer.open(filename, family, prefix="AS%s" % asn)
 
@@ -258,6 +289,11 @@ class Exporter(object):
                        for writer in writers.values():
                                writer.finish()
 
+                       # Print to stdout
+                       if not directory:
+                               for writer in writers.values():
+                                       writer.print()
+
        def _make_filename(self, directory, prefix, suffix, family):
                filename = "%s.%s%s" % (
                        prefix, suffix, "6" if family == socket.AF_INET6 else "4"
index eec32e4ca966c8973be32d40d086557fce177ef7..89e9fcee80b75295acd6123b579a6b90d38dd136 100644 (file)
@@ -181,7 +181,7 @@ class CLI(object):
                )
                export.add_argument("--format", help=_("Output format"),
                        choices=location.export.formats.keys(), default="list")
-               export.add_argument("--directory", help=_("Output directory"), required=True)
+               export.add_argument("--directory", help=_("Output directory"))
                export.add_argument("--family",
                        help=_("Specify address family"), choices=("ipv6", "ipv4"),
                )