Example #1
0
def list_npm_modules(collector, no_print=False):
    """List the npm modules that get installed in a docker image for the react server"""
    default = ReactServer().default_npm_deps()
    for _, module in sorted(collector.configuration["__active_modules__"].items()):
        default.update(module.npm_deps())

    if not no_print:
        print(json.dumps(default, indent=4, sort_keys=True))
    return default
Example #2
0
    def __init__(
        self,
        host,
        port,
        debug,
        dashboards,
        modules,
        module_options,
        datastore,
        dynamic_dashboard_js,
        compiled_static_prep,
        compiled_static_folder,
        without_checks,
    ):
        self.thread_stopper = {"finished": False}

        self.host = host
        self.port = port
        self.modules = modules
        self.datastore = datastore
        self.dashboards = dashboards
        self.module_options = module_options
        self.without_checks = without_checks
        self.dynamic_dashboard_js = dynamic_dashboard_js

        self.compiled_static_prep = compiled_static_prep
        self.compiled_static_folder = compiled_static_folder

        self.react_server = ReactServer()
Example #3
0
def collect_dashboard_js(collector):
    """Generate dashboard javascript for each dashboard"""
    dashmat = collector.configuration["dashmat"]

    modules = collector.configuration["__active_modules__"]
    compiled_static_prep = dashmat.compiled_static_prep
    compiled_static_folder = dashmat.compiled_static_folder

    npm_deps = list_npm_modules(collector, no_print=True)
    react_server = ReactServer()
    react_server.prepare(npm_deps, compiled_static_folder)

    for dashboard in collector.configuration["dashboards"].values():
        log.info("Generating compiled javascript for dashboard:{0}".format(dashboard.path))
        filename = dashboard.path.replace("_", "__").replace("/", "_")
        location = os.path.join(compiled_static_folder, "dashboards", "{0}.js".format(filename))
        if os.path.exists(location):
            os.remove(location)
        generate_dashboard_js(dashboard, react_server, compiled_static_folder, compiled_static_prep, modules)
Example #4
0
class Server(object):
    def __init__(
        self,
        host,
        port,
        debug,
        dashboards,
        modules,
        module_options,
        datastore,
        dynamic_dashboard_js,
        compiled_static_prep,
        compiled_static_folder,
        without_checks,
    ):
        self.thread_stopper = {"finished": False}

        self.host = host
        self.port = port
        self.modules = modules
        self.datastore = datastore
        self.dashboards = dashboards
        self.module_options = module_options
        self.without_checks = without_checks
        self.dynamic_dashboard_js = dynamic_dashboard_js

        self.compiled_static_prep = compiled_static_prep
        self.compiled_static_folder = compiled_static_folder

        self.react_server = ReactServer()

    def serve(self):
        http_server = HTTPServer(WSGIContainer(self.app))
        scheduler = Scheduler(self.datastore)
        if not self.without_checks:
            for name, (module, server) in self.servers.items():
                scheduler.register(module, server, name)

        try:
            if not self.without_checks:
                scheduler.start()
            http_server.listen(self.port, self.host)
            log.info("Starting server on http://%s:%s", self.host, self.port)

            try:
                IOLoop.instance().start()
            finally:
                self.thread_stopper["finished"] = True
        finally:
            scheduler.finish()

    @property
    def app(self):
        if getattr(self, "_app", None) is None:
            self._app = Flask("dashmat.server")

            # Remove auto generated static route
            while self._app.url_map._rules:
                self._app.url_map._rules.pop()
            for key in list(self._app.url_map._rules_by_endpoint):
                self._app.url_map._rules_by_endpoint.pop(key)
            self._app.url_map.update()
            self._app.view_functions.clear()

            self.servers = {}
            for name, module in self.modules.items():
                self.servers[name] = (module, module.make_server(self.module_options[name].server_options))

            # Register our own routes
            self.register_routes(self._app)

            if self.dynamic_dashboard_js:
                # Prepare the docker image for translating jsx into javascript
                deps = {}
                for _, module in sorted(self.modules.items()):
                    deps.update(module.npm_deps())
                self.react_server.prepare(deps, self.compiled_static_folder)
        return self._app

    def register_routes(self, app):
        class EverythingConverter(PathConverter):
            regex = ".*?"

        app.url_map.converters["everything"] = EverythingConverter

        def make_view(func, module, module_name):
            @wraps(func)
            def wrapper(*args, **kwargs):
                ds = self.datastore.prefixed("{0}-{1}".format(module.relative_to, module_name))
                res = func(ds, *args, **kwargs)
                return flask.jsonify({"value": res})

            return wrapper

        for name, (module, server) in self.servers.items():
            try:
                for route_name, func in server.routes:
                    view = make_view(func, module, name)
                    view.__name__ = "server_route_{0}_{1}".format(name, route_name)
                    route = "/data/{0}/{1}".format(name, route_name)
                    log.info("Adding route %s", route)
                    app.route(route)(view)
            except Exception as error:
                raise DashMatError("Failed to setup routes for a server", server=server, error=error)

        @app.route("/diagnostic/status/heartbeat", methods=["GET"])
        def heartbeat():
            return ""

        @app.route("/diagnostic/status/nagios", methods=["GET"])
        def nagios():
            return "OK"

        @app.route("/diagnostic/version", methods=["Get"])
        def version():
            static_dir = os.path.join(here, "static")
            return send_from_directory(static_dir, "version")

        @app.route("/static/dashboards/<everything:path>", methods=["GET"])
        def static_dashboards(path):
            if path not in self.dashboards:
                raise abort(404)

            location = generate_dashboard_js(
                self.dashboards[path],
                self.react_server,
                self.compiled_static_folder,
                self.compiled_static_prep,
                self.modules,
                dynamic_dashboard_js=self.dynamic_dashboard_js,
            )

            return send_from_directory(os.path.dirname(location), os.path.basename(location))

        @app.route("/static/css/<import_path>/<path:name>", methods=["GET"])
        def static_css(import_path, name):
            static_folder = pkg_resources.resource_filename(import_path, "static")
            static_file = os.path.join(static_folder, name)
            if os.path.exists(static_file):
                return send_from_directory(static_folder, name)
            else:
                raise abort(404)

        def make_dashboard(path, dashboard):
            def dashboard_view():
                title = path.replace("/", " ").replace("_", " ").title()
                css = []
                enabled_modules = list(dashboard.enabled_modules)
                for imprt in dashboard.imports:
                    if hasattr(imprt, "module_name"):
                        if isinstance(imprt.module_name, six.string_types):
                            module = self.modules[imprt.module_name]
                        elif isinstance(imprt.module_name, dict):
                            module = imprt.module_name["import_path"]
                        else:
                            module = imprt.module_name
                        enabled_modules.append(module)

                def add_dependencies():
                    added = False
                    for module in enabled_modules:
                        for dependency in module.dependencies():
                            if self.modules[dependency] not in enabled_modules:
                                enabled_modules.append(self.modules[dependency])
                                added = True
                    if added:
                        add_dependencies()

                add_dependencies()

                first_state = {}
                for module in enabled_modules:
                    css.extend(["/static/css/{0}/{1}".format(module.relative_to, c) for c in module.css()])

                for name, (module, server) in self.servers.items():
                    for route_name, func in server.routes:
                        route = "/data/{0}/{1}".format(name, route_name)
                        ds = self.datastore.prefixed("{0}-{1}".format(module.relative_to, name))
                        first_state[route] = func(ds)

                return render_template(
                    "index.html",
                    dashboardjs="/static/dashboards/{0}".format(path),
                    title=title,
                    css=css,
                    first_state=json.dumps(first_state),
                )

            dashboard_view.__name__ = "dashboard_{0}".format(path.replace("_", "__").replace("/", "_"))
            return dashboard_view

        for path, dashboard in self.dashboards.items():
            app.route(path, methods=["GET"])(make_dashboard(path, dashboard))