Example #1
0
    def test_json_to_yaml(self):
        """
        Running `crossbar convert` with a YAML config file will convert it to
        JSON.
        """
        cbdir = self.mktemp()
        os.makedirs(cbdir)
        config_file = os.path.join(cbdir, "config.json")
        with open(config_file, 'w') as f:
            f.write("""{
   "foo": {
      "bar": "spam",
      "baz": {
         "foo": "cat"
      }
   }
}""")

        main.main("crossbar",
                  ["convert", "--config={}".format(config_file)])

        self.assertIn(
            ("YAML formatted configuration written"),
            self.stdout.getvalue())

        with open(os.path.join(cbdir, "config.yaml"), 'r') as f:
            self.assertEqual(f.read(), """foo:
  bar: spam
  baz:
    foo: cat
""")
Example #2
0
    def _start_run(self, config, app, stdout_expected, stderr_expected,
                   end_on):

        with open(self.config, "wb") as f:
            f.write(json.dumps(config, ensure_ascii=False).encode('utf8'))

        with open(self.code_location + "/myapp.py", "w") as f:
            f.write(app)

        reactor = SelectReactor()

        make_lc(self, reactor, end_on)

        # In case it hard-locks
        reactor.callLater(self._subprocess_timeout, reactor.stop)

        main.main("crossbar",
                  ["start",
                   "--cbdir={}".format(self.cbdir),
                   "--logformat=syslogd"],
                  reactor=reactor)

        out = self.stdout.getvalue()
        err = self.stderr.getvalue()
        for i in stdout_expected:
            if i not in out:
                self.fail("Error: '{}' not in:\n{}".format(i, out))

        for i in stderr_expected:
            if i not in err:
                self.fail("Error: '{}' not in:\n{}".format(i, err))
Example #3
0
    def _start_run(self, config, app, stdout_expected, stderr_expected,
                   end_on):

        with open(self.config, "wb") as f:
            f.write(json.dumps(config, ensure_ascii=False).encode('utf8'))

        with open(self.code_location + "/myapp.py", "w") as f:
            f.write(app)

        reactor = SelectReactor()

        make_lc(self, reactor, end_on)

        # In case it hard-locks
        reactor.callLater(self._subprocess_timeout, reactor.stop)

        main.main("crossbar",
                  ["start",
                   "--cbdir={}".format(self.cbdir),
                   "--logformat=syslogd"],
                  reactor=reactor)

        out = self.stdout.getvalue()
        err = self.stderr.getvalue()
        for i in stdout_expected:
            if i not in out:
                self.fail(u"Error: '{}' not in:\n{}".format(i, out))

        for i in stderr_expected:
            if i not in err:
                self.fail(u"Error: '{}' not in:\n{}".format(i, err))
Example #4
0
    def test_json_to_yaml(self):
        """
        Running `crossbar convert` with a YAML config file will convert it to
        JSON.
        """
        cbdir = self.mktemp()
        os.makedirs(cbdir)
        config_file = os.path.join(cbdir, "config.json")
        with open(config_file, 'w') as f:
            f.write("""{
   "foo": {
      "bar": "spam",
      "baz": {
         "foo": "cat"
      }
   }
}""")

        main.main("crossbar", ["convert", "--config={}".format(config_file)])

        self.assertIn(("YAML formatted configuration written"),
                      self.stdout.getvalue())

        with open(os.path.join(cbdir, "config.yaml"), 'r') as f:
            self.assertEqual(f.read(), """foo:
  bar: spam
  baz:
    foo: cat
""")
Example #5
0
    def test_basic(self):
        """
        Just running `crossbar version` gets us the versions.
        """
        reactor = SelectReactor()

        main.main("crossbar", ["version"], reactor=reactor)

        self.assertIn("Crossbar.io", self.stdout.getvalue())
        self.assertIn(("Twisted          : \x1b[33m\x1b[1m" +
                       twisted.version.short() + "-SelectReactor"),
                      self.stdout.getvalue())
Example #6
0
    def test_basic(self):
        """
        Just running `crossbar version` gets us the versions.
        """
        reactor = SelectReactor()

        main.main("crossbar",
                  ["version"],
                  reactor=reactor)

        self.assertIn("Crossbar.io", self.stdout.getvalue())
        self.assertIn(
            ("Twisted          : \x1b[33m\x1b[1m" + twisted.version.short() + "-SelectReactor"),
            self.stdout.getvalue())
Example #7
0
    def test_debug(self):
        """
        Running `crossbar version` will give us the versions, plus the
        locations of some of them.
        """
        reactor = SelectReactor()

        main.main("crossbar", ["version", "--loglevel=debug"], reactor=reactor)

        self.assertIn("Crossbar.io", self.stdout.getvalue())
        self.assertIn(("Twisted          : \x1b[33m\x1b[1m" +
                       twisted.version.short() + "-SelectReactor"),
                      self.stdout.getvalue())
        self.assertIn(("[twisted.internet.selectreactor.SelectReactor]"),
                      self.stdout.getvalue())
Example #8
0
    def test_start(self):
        """
        A basic start, that doesn't actually enter the reactor.
        """
        with open(self.config, "w") as f:
            f.write("""{"controller": {}}""")

        reactor = SelectReactor()
        reactor.run = lambda: False

        main.main("crossbar",
                  ["start", "--cbdir={}".format(self.cbdir),
                   "--logformat=syslogd"],
                  reactor=reactor)

        self.assertIn("Entering reactor event loop", self.stdout.getvalue())
Example #9
0
    def test_start(self):
        """
        A basic start, that doesn't actually enter the reactor.
        """
        with open(self.config, "w") as f:
            f.write("""{"controller": {}}""")

        reactor = SelectReactor()
        reactor.run = lambda: False

        main.main(
            "crossbar",
            ["start", "--cbdir={}".format(self.cbdir), "--logformat=syslogd"],
            reactor=reactor)

        self.assertIn("Entering reactor event loop", self.stdout.getvalue())
Example #10
0
    def test_invalid_json_to_yaml(self):
        """
        Running `crossbar convert` with an invalid JSON config file will error
        saying it is invalid.
        """
        cbdir = self.mktemp()
        os.makedirs(cbdir)
        config_file = os.path.join(cbdir, "config.json")
        with open(config_file, 'w') as f:
            f.write("""{{{{{{{{""")

        with self.assertRaises(SystemExit) as e:
            main.main("crossbar",
                      ["convert", "--config={}".format(config_file)])

        self.assertEqual(e.exception.args[0], 1)
        self.assertIn(("not seem to be proper JSON"), self.stdout.getvalue())
Example #11
0
    def test_unknown_format(self):
        """
        Running `crossbar convert` with an unknown config file produces an
        error.
        """
        cbdir = self.mktemp()
        os.makedirs(cbdir)
        config_file = os.path.join(cbdir, "config.blah")
        open(config_file, 'wb').close()

        with self.assertRaises(SystemExit) as e:
            main.main("crossbar",
                      ["convert", "--config={}".format(config_file)])

        self.assertEqual(e.exception.args[0], 1)
        self.assertIn(
            ("Error: configuration file needs to be '.json' or '.yaml'."),
            self.stdout.getvalue())
Example #12
0
    def test_unknown_format(self):
        """
        Running `crossbar convert` with an unknown config file produces an
        error.
        """
        cbdir = self.mktemp()
        os.makedirs(cbdir)
        config_file = os.path.join(cbdir, "config.blah")
        open(config_file, 'wb').close()

        with self.assertRaises(SystemExit) as e:
            main.main("crossbar",
                      ["convert", "--config={}".format(config_file)])

        self.assertEqual(e.exception.args[0], 1)
        self.assertIn(
            ("Error: configuration file needs to be '.json' or '.yaml'."),
            self.stdout.getvalue())
Example #13
0
    def test_debug(self):
        """
        Running `crossbar version` will give us the versions, plus the
        locations of some of them.
        """
        reactor = SelectReactor()

        main.main("crossbar",
                  ["version", "--loglevel=debug"],
                  reactor=reactor)

        self.assertIn("Crossbar.io", self.stdout.getvalue())
        self.assertIn(
            ("Twisted          : \x1b[33m\x1b[1m" + twisted.version.short() + "-SelectReactor"),
            self.stdout.getvalue())
        self.assertIn(
            ("[twisted.internet.selectreactor.SelectReactor]"),
            self.stdout.getvalue())
Example #14
0
    def test_invalid_json_to_yaml(self):
        """
        Running `crossbar convert` with an invalid JSON config file will error
        saying it is invalid.
        """
        cbdir = self.mktemp()
        os.makedirs(cbdir)
        config_file = os.path.join(cbdir, "config.json")
        with open(config_file, 'w') as f:
            f.write("""{{{{{{{{""")

        with self.assertRaises(SystemExit) as e:
            main.main("crossbar",
                      ["convert", "--config={}".format(config_file)])

        self.assertEqual(e.exception.args[0], 1)
        self.assertIn(
            ("not seem to be proper JSON"),
            self.stdout.getvalue())
Example #15
0
    def test_fileLogging(self):
        """
        Running `crossbar start --logtofile` will log to cbdir/node.log.
        """
        with open(self.config, "w") as f:
            f.write("""{"controller": {}}""")

        reactor = SelectReactor()
        reactor.run = lambda: None

        main.main("crossbar",
                  ["start", "--cbdir={}".format(self.cbdir), "--logtofile"],
                  reactor=reactor)

        with open(os.path.join(self.cbdir, "node.log"), "r") as f:
            logFile = f.read()

        self.assertIn("Entering reactor event loop", logFile)
        self.assertEqual("", self.stderr.getvalue())
        self.assertEqual("", self.stdout.getvalue())
Example #16
0
    def test_fileLogging(self):
        """
        Running `crossbar start --logtofile` will log to cbdir/node.log.
        """
        with open(self.config, "w") as f:
            f.write("""{"controller": {}}""")

        reactor = SelectReactor()
        reactor.run = lambda: None

        main.main("crossbar",
                  ["start", "--cbdir={}".format(self.cbdir), "--logtofile"],
                  reactor=reactor)

        with open(os.path.join(self.cbdir, "node.log"), "r") as f:
            logFile = f.read()

        self.assertIn("Entering reactor event loop", logFile)
        self.assertEqual("", self.stderr.getvalue())
        self.assertEqual("", self.stdout.getvalue())
Example #17
0
    def test_hello(self):

        def _check(lc, reactor):
            if "published to 'oncounter'" in self.stdout.getvalue():
                lc.stop()
                try:
                    reactor.stop()
                except:
                    pass

        appdir = self.mktemp()
        cbdir = os.path.join(appdir, ".crossbar")

        reactor = SelectReactor()
        main.main("crossbar",
                  ["init",
                   "--appdir={}".format(appdir),
                   "--template=hello:python"],
                  reactor=reactor)

        self.assertIn("Application template initialized",
                      self.stdout.getvalue())

        reactor = SelectReactor()
        make_lc(self, reactor, _check)

        # In case it hard-locks
        reactor.callLater(self._subprocess_timeout, reactor.stop)

        main.main("crossbar",
                  ["start",
                   "--cbdir={}".format(cbdir.path),
                   "--logformat=syslogd"],
                  reactor=reactor)

        stdout_expected = ["published to 'oncounter'"]

        for i in stdout_expected:
            self.assertIn(i, self.stdout.getvalue())
Example #18
0
    def test_stalePID(self):

        with open(self.config, "w") as f:
            f.write("""{"controller": {}}""")

        with open(os.path.join(self.cbdir, "node.pid"), "w") as f:
            f.write("""{"pid": 9999999}""")

        reactor = SelectReactor()
        reactor.run = lambda: None

        main.main("crossbar",
                  ["start", "--cbdir={}".format(self.cbdir),
                   "--logformat=syslogd"],
                  reactor=reactor)

        self.assertIn(
            ("Stale Crossbar.io PID file (pointing to non-existing process "
             "with PID {pid}) {fp} removed").format(
                 fp=os.path.abspath(os.path.join(self.cbdir, "node.pid")),
                 pid=9999999),
            self.stdout.getvalue())
Example #19
0
    def test_stalePID(self):

        with open(self.config, "w") as f:
            f.write("""{"controller": {}}""")

        with open(os.path.join(self.cbdir, "node.pid"), "w") as f:
            f.write("""{"pid": 9999999}""")

        reactor = SelectReactor()
        reactor.run = lambda: None

        main.main(
            "crossbar",
            ["start", "--cbdir={}".format(self.cbdir), "--logformat=syslogd"],
            reactor=reactor)

        self.assertIn(
            ("Stale Crossbar.io PID file (pointing to non-existing process "
             "with PID {pid}) {fp} removed").format(fp=os.path.abspath(
                 os.path.join(self.cbdir, "node.pid")),
                                                    pid=9999999),
            self.stdout.getvalue())
Example #20
0
    def test_hello(self):

        def _check(lc, reactor):
            if "published to 'oncounter'" in self.stdout.getvalue():
                lc.stop()
                try:
                    reactor.stop()
                except:
                    pass

        appdir = self.mktemp()
        cbdir = os.path.join(appdir, ".crossbar")

        reactor = SelectReactor()
        main.main("crossbar",
                  ["init",
                   "--appdir={}".format(appdir),
                   "--template=hello:python"],
                  reactor=reactor)

        self.assertIn("Application template initialized",
                      self.stdout.getvalue())

        reactor = SelectReactor()
        make_lc(self, reactor, _check)

        # In case it hard-locks
        reactor.callLater(self._subprocess_timeout, reactor.stop)

        main.main("crossbar",
                  ["start",
                   "--cbdir={}".format(cbdir.path),
                   "--logformat=syslogd"],
                  reactor=reactor)

        stdout_expected = ["published to 'oncounter'"]

        for i in stdout_expected:
            self.assertIn(i, self.stdout.getvalue())
Example #21
0
    def test_configValidationFailure(self):
        """
        Running `crossbar start` with an invalid config will print a warning.
        """
        with open(self.config, "w") as f:
            f.write("")

        reactor = SelectReactor()

        with self.assertRaises(SystemExit) as e:
            main.main("crossbar", [
                "start", "--cbdir={}".format(self.cbdir), "--logformat=syslogd"
            ],
                      reactor=reactor)

        # Exit with code 1
        self.assertEqual(e.exception.args[0], 1)

        # The proper warning should be emitted
        self.assertIn("*** Configuration validation failed ***",
                      self.stderr.getvalue())
        self.assertIn(("configuration file does not seem to be proper JSON "),
                      self.stderr.getvalue())
Example #22
0
    def test_configValidationFailure(self):
        """
        Running `crossbar start` with an invalid config will print a warning.
        """
        with open(self.config, "w") as f:
            f.write("")

        reactor = SelectReactor()

        with self.assertRaises(SystemExit) as e:
            main.main("crossbar",
                      ["start", "--cbdir={}".format(self.cbdir),
                       "--logformat=syslogd"],
                      reactor=reactor)

        # Exit with code 1
        self.assertEqual(e.exception.args[0], 1)

        # The proper warning should be emitted
        self.assertIn("*** Configuration validation failed ***",
                      self.stderr.getvalue())
        self.assertIn(("configuration file does not seem to be proper JSON "),
                      self.stderr.getvalue())
Example #23
0
def run(args=None, reactor=None, personality=None):
    """
    Main entry point into Crossbar.io:

    * when called with no arguments, the arguments are read
      from the command line

    * when called with an explicit arguments list, use the same
      arguments in the list as on the command line, leaving out
      the initial `crossbar` command.


    twisted.internet.error.ReactorNotRestartable

    **Examples**

    To start Crossbar.io programmatically from a given node directory:

    .. code-block:: python

        import crossbar

        crossbar.run(['start', '--cbdir', '/tmp/mynode1/.crossbar'])

    To start Crossbar.io with log output at level "debug"

    .. code-block:: console

        $ crossbar start --loglevel=debug

    To chose a specific event reactor and print version information

    .. code-block:: console

        $ CROSSBAR_REACTOR="kqueue" crossbar version

    To start from a specified node directory (instead of the default `$CWD/.crossbar`):

    .. code-block:: console

        $ CROSSBAR_DIR="/tmp/test/.crossbar" crossbar start

    which is the same as

    .. code-block:: console

        $ crossbar start --cbdir=/tmp/test/.crossbar

   **Influential command line options and environment variables include:**

    ==================  ========================  ==============================================
    Command line arg:   Environment variable:     Description:
    ==================  ========================  ==============================================
    n.a.                **CROSSBAR_REACTOR**      Event reactor:

                                                  * **auto**
                                                  * **select**
                                                  * **poll**
                                                  * **epoll**
                                                  * **kqueue**
                                                  * **iocp**

    n.a.                **CROSSBAR_PERSONALITY**  Node personality:

                                                  * **standalone**
                                                  * **edge**
                                                  * **master**

    ``--cbdir``         **CROSSBAR_DIR**          Node directory (local directory)
    ``--config``        **CROSSBAR_CONFIG**       Node configuration (local filename)
    ``--color``         n.a.                      Enable colored terminal output
    ``--loglevel``      n.a.                      Select log level
    ``--logformat``     n.a.                      Select log format
    ``--logdir``        n.a.                      Log to this local directory
    ``--logtofile``     n.a.                      Enable logging to file
    ==================  ========================  ==============================================

    .. seealso:: `TwistedMatrix: Choosing a Reactor and GUI Toolkit Integration <https://twistedmatrix.com/documents/current/core/howto/choosing-reactor.html>`_

    .. note:: The Twisted reactor to use can only be explicitly chosen via an environment
        variable, not a command line option.

    :param args: The (optional) program name .
    :type args: List[str]

    :param reactor: Optional Twisted reactor to use. If none is given, try to
        load the optimal reactor for Crossbar.io to run on the host platform.
    :type reactor: :class:`twisted.internet.reactor`
    """
    import sys
    import os
    from autobahn.twisted import install_reactor

    if reactor is not None and reactor not in _DEFINED_REACTORS:
        raise Exception('illegal value "{}" for reactor'.format(reactor))

    if personality is not None and personality not in _DEFINED_PERSONALITIES:
        raise Exception(
            'illegal value "{}" for personality. Valid: {}'.format(
                personality,
                ", ".join(_DEFINED_PERSONALITIES),
            )
        )

    # use argument list from command line if none is given explicitly
    if args is None:
        exename = os.path.basename(sys.argv[0])
        args = sys.argv[1:]
    else:
        exename = 'crossbar'

    # IMPORTANT: keep the reactor install as early as possible to avoid importing
    # any Twisted module that comes with the side effect of installing a default
    # reactor (which might not be what we want!).
    if reactor is None:
        # we use an Autobahn utility to import the "best" available Twisted reactor
        reactor = install_reactor(explicit_reactor=os.environ.get('CROSSBAR_REACTOR', None),
                                  verbose=False,
                                  require_optimal_reactor=False)

    # Twisted reactor installed FROM HERE ***

    # get installed personalities
    _personalities = personalities()

    # set personality
    if not personality:

        # choose node personality to run
        if 'CROSSBAR_PERSONALITY' in os.environ:
            personality = os.environ['CROSSBAR_PERSONALITY']
            if personality not in _DEFINED_PERSONALITIES:
                raise Exception(
                    'illegal value "{}" for personality (from CROSSBAR_PERSONALITY environment variable): {}'.format(
                        personality,
                        ", ".join(_DEFINED_PERSONALITIES),
                    )
                )
        else:
            personality = 'standalone'

    if personality not in _personalities:
        raise Exception('fatal: no personality "{}" [{}]'.format(personality, sorted(_personalities.keys())))

    # get chosen personality class
    personality_klass = _personalities[personality]

    # do NOT move this import above *** (triggers reactor imports)
    from crossbar.node.main import main

    # and now actually enter here .. this never returns!
    return main(exename, args, reactor, personality_klass)
Example #24
0
def run(args=None, reactor=None, personality=None):
    """
    Main entry point into Crossbar.io:

    * when called with no arguments, the arguments are read
      from the command line

    * when called with an explicit arguments list, use the same
      arguments in the list as on the command line, leaving out
      the initial `crossbar` command.


    twisted.internet.error.ReactorNotRestartable

    **Examples**

    To start Crossbar.io programmatically from a given node directory:

    .. code-block:: python

        import crossbar

        crossbar.run(['start', '--cbdir', '/tmp/mynode1/.crossbar'])

    To start Crossbar.io with log output at level "debug"

    .. code-block:: console

        $ crossbar start --loglevel=debug

    To chose a specific event reactor and print version information

    .. code-block:: console

        $ CROSSBAR_REACTOR="kqueue" crossbar version

    To start from a specified node directory (instead of the default `$CWD/.crossbar`):

    .. code-block:: console

        $ CROSSBAR_DIR="/tmp/test/.crossbar" crossbar start

    which is the same as

    .. code-block:: console

        $ crossbar start --cbdir=/tmp/test/.crossbar

   **Influential command line options and environment variables include:**

    ==================  ========================  ==============================================
    Command line arg:   Environment variable:     Description:
    ==================  ========================  ==============================================
    n.a.                **CROSSBAR_REACTOR**      Event reactor:

                                                  * **auto**
                                                  * **select**
                                                  * **poll**
                                                  * **epoll**
                                                  * **kqueue**
                                                  * **iocp**

    n.a.                **CROSSBAR_PERSONALITY**  Node personality:

                                                  * **standalone**
                                                  * **fabric**
                                                  * **fabricenter**

    ``--cbdir``         **CROSSBAR_DIR**          Node directory (local directory)
    ``--config``        **CROSSBAR_CONFIG**       Node configuration (local filename)
    ``--color``         n.a.                      Enable colored terminal output
    ``--loglevel``      n.a.                      Select log level
    ``--logformat``     n.a.                      Select log format
    ``--logdir``        n.a.                      Log to this local directory
    ``--logtofile``     n.a.                      Enable logging to file
    ==================  ========================  ==============================================

    .. seealso:: `TwistedMatrix: Choosing a Reactor and GUI Toolkit Integration <https://twistedmatrix.com/documents/current/core/howto/choosing-reactor.html>`_

    .. note:: The Twisted reactor to use can only be explicitly chosen via an environment
        variable, not a command line option.

    :param args: The (optional) program name .
    :type args: List[str]

    :param reactor: Optional Twisted reactor to use. If none is given, try to
        load the optimal reactor for Crossbar.io to run on the host platform.
    :type reactor: :class:`twisted.internet.reactor`
    """
    import sys
    import os
    from autobahn.twisted import install_reactor

    if reactor is not None and reactor not in _DEFINED_REACTORS:
        raise Exception('illegal value "{}" for reactor'.format(reactor))

    if personality is not None and personality not in _DEFINED_PERSONALITIES:
        raise Exception('illegal value "{}" for personality'.format(personality))

    # use argument list from command line if none is given explicitly
    if args is None:
        exename = os.path.basename(sys.argv[0])
        args = sys.argv[1:]
    else:
        exename = 'crossbar'

    # IMPORTANT: keep the reactor install as early as possible to avoid importing
    # any Twisted module that comes with the side effect of installing a default
    # reactor (which might not be what we want!).
    if reactor is None:
        # we use an Autobahn utility to import the "best" available Twisted reactor
        reactor = install_reactor(explicit_reactor=os.environ.get('CROSSBAR_REACTOR', None),
                                  verbose=False,
                                  require_optimal_reactor=False)

    # Twisted reactor installed FROM HERE ***

    # get installed personalities
    _personalities = personalities()

    # set personality
    if not personality:

        # choose node personality to run
        if 'CROSSBAR_PERSONALITY' in os.environ:
            personality = os.environ['CROSSBAR_PERSONALITY']
            if personality not in _DEFINED_PERSONALITIES:
                raise Exception('illegal value "{}" for personality (from CROSSBAR_PERSONALITY environment variable)'.format(personality))
        else:
            if _SELECT_MAX_PERSONALITY_AS_DEFAULT:
                if 'fabriccenter' in _personalities:
                    personality = 'fabriccenter'
                elif 'fabric' in _personalities:
                    personality = 'fabric'
                elif 'standalone' in _personalities:
                    personality = 'standalone'
                else:
                    raise Exception('logic error')
            else:
                personality = 'standalone'

    if personality not in _personalities:
        raise Exception('fatal: no personality "{}"'.format(personality))

    # get chosen personality class
    personality_klass = _personalities[personality]

    # do NOT move this import above *** (triggers reactor imports)
    from crossbar.node.main import main

    # and now actually enter here .. this never returns!
    return main(exename, args, reactor, personality_klass)