Module jumpscale.servers.openresty.server

Expand source code
from jumpscale.loader import j
from enum import Enum
from jumpscale.core.base import Base, fields
from .location import Location
from .utils import render_config_template, DIR_PATH


class Status(Enum):
    INIT = "init"
    INSTALLED = "installed"


class Website(Base):

    port = fields.Integer(default=80)
    ssl = fields.Boolean()
    domain = fields.String()
    path = fields.String()
    locations = fields.Factory(Location)

    @property
    def path_cfg_dir(self):
        return f"{self.parent.path_cfg_dir}/servers"

    @property
    def path_cfg(self):
        return f"{self.path_cfg_dir}/{self.instance_name}.http.conf"

    @property
    def path_web(self):
        return self.parent.path_web

    def configure(self):
        """Writes configuration of the website and its locations"""

        j.sals.fs.mkdir(self.path_cfg_dir)
        config = render_config_template("website", base_dir=j.core.dirs.BASEDIR, website=self)
        j.sals.fs.write_file(self.path_cfg, config)

        for location_name in self.locations.list_all():
            location = self.locations.get(location_name)
            location.configure()


class OpenRestyServer(Base):
    status = fields.Enum(Status)
    websites = fields.Factory(Website)

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self._cmd = None
        self._path_web = None
        self._path_cfg_dir = None
        self._logs_dir = None

        self.executor = "tmux"  # only tmux for now

    @property
    def path_web(self):
        if not self._path_web:
            self._path_web = j.sals.fs.join_paths(j.core.dirs.VARDIR, "web", self.instance_name)
            j.sals.fs.mkdirs(j.sals.fs.join_paths(self._path_web, "static"))
        return self._path_web

    @property
    def path_cfg_dir(self):
        if not self._path_cfg_dir:
            self._path_cfg_dir = j.sals.fs.join_paths(j.core.dirs.CFGDIR, "nginx", self.instance_name)
            j.sals.fs.mkdirs(self._path_cfg_dir)
        return self._path_cfg_dir

    @property
    def path_cfg(self):
        return j.sals.fs.join_paths(self.path_cfg_dir, "nginx.conf")

    @property
    def logs_dir(self):
        if not self._logs_dir:
            self._logs_dir = j.sals.fs.join_paths(j.core.dirs.LOGDIR, "openresty", self.instance_name)
            j.sals.fs.mkdirs(self._logs_dir)
        return self._logs_dir

    def configure(self):
        """configures main nginx conf"""
        # clean old websites config
        self.cleanup()

        # self.install() This is commented for now until the repo and necessary deps are handled
        configtext = j.tools.jinja2.render_template(
            template_path=j.sals.fs.join_paths(DIR_PATH, "templates", "nginx.conf"), logs_dir=self.logs_dir
        )
        j.sals.fs.write_file(self.path_cfg, configtext)

    def get_from_port(self, port, domain=None, ssl=None):
        """will try to get a website listening on port, if it doesn't exist it will create one

        Args:
            port (int): port to search for
            domain (str, optional): domain. Defaults to None.
            ssl (bool, optional): Will set ssl if True. Defaults to None.

        Returns:
            Website: A new or an old website instance with the needed port
        """
        website_name = f"{self.instance_name}_website_{port}"

        website = self.websites.find(website_name)
        if website:
            return website

        website = self.websites.get(website_name)
        ssl = ssl or port == 443  # Use ssl if port is 443 if ssl in not specified

        website.domain = domain
        website.port = port
        website.ssl = ssl

        return website

    def install(self, reset=False):
        """Install required deps for openresty

        Args:
            reset (bool, optional): If true will redo the installation. Defaults to False.
        """
        if reset or self.status == "init":
            # get weblib
            weblibs_path = j.tools.git.ensure_repo(
                "https://github.com/threefoldtech/js-weblibs"  # Place holder repo might be changed
            )

            # copy the templates to the right location
            j.sals.fs.copy_tree(f"{DIR_PATH}/web_resources/", self.path_cfg_dir)

            j.sals.fs.symlink(f"{weblibs_path}/static", f"{self.path_web}/static/weblibs", overwrite=True)
            self.status = Status.INSTALLED

            self.save()

    @property
    def startup_cmd(self):
        pass

    def start(self, reset=False):
        pass

    def stop(self):
        pass

    def is_running(self):
        pass

    def reload(self):
        self.configure()
        j.sals.process.execute("lapis build", cwd=self.path_cfg_dir)

    def cleanup(self):
        j.sals.fs.rmtree(f"{self.path_cfg_dir}/servers")

Classes

class OpenRestyServer (**kwargs)

A simple attribute-based namespace.

SimpleNamespace(**kwargs)

base class implementation for any class with fields which supports getting/setting raw data for any instance fields.

any instance can have an optional name and a parent.

class Person(Base):
    name = fields.String()
    age = fields.Float()

p = Person(name="ahmed", age="19")
print(p.name, p.age)

Args

parent_ : Base, optional
parent instance. Defaults to None.
instance_name_ : str, optional
instance name. Defaults to None.
**values
any given field values to initiate the instance with
Expand source code
class OpenRestyServer(Base):
    status = fields.Enum(Status)
    websites = fields.Factory(Website)

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self._cmd = None
        self._path_web = None
        self._path_cfg_dir = None
        self._logs_dir = None

        self.executor = "tmux"  # only tmux for now

    @property
    def path_web(self):
        if not self._path_web:
            self._path_web = j.sals.fs.join_paths(j.core.dirs.VARDIR, "web", self.instance_name)
            j.sals.fs.mkdirs(j.sals.fs.join_paths(self._path_web, "static"))
        return self._path_web

    @property
    def path_cfg_dir(self):
        if not self._path_cfg_dir:
            self._path_cfg_dir = j.sals.fs.join_paths(j.core.dirs.CFGDIR, "nginx", self.instance_name)
            j.sals.fs.mkdirs(self._path_cfg_dir)
        return self._path_cfg_dir

    @property
    def path_cfg(self):
        return j.sals.fs.join_paths(self.path_cfg_dir, "nginx.conf")

    @property
    def logs_dir(self):
        if not self._logs_dir:
            self._logs_dir = j.sals.fs.join_paths(j.core.dirs.LOGDIR, "openresty", self.instance_name)
            j.sals.fs.mkdirs(self._logs_dir)
        return self._logs_dir

    def configure(self):
        """configures main nginx conf"""
        # clean old websites config
        self.cleanup()

        # self.install() This is commented for now until the repo and necessary deps are handled
        configtext = j.tools.jinja2.render_template(
            template_path=j.sals.fs.join_paths(DIR_PATH, "templates", "nginx.conf"), logs_dir=self.logs_dir
        )
        j.sals.fs.write_file(self.path_cfg, configtext)

    def get_from_port(self, port, domain=None, ssl=None):
        """will try to get a website listening on port, if it doesn't exist it will create one

        Args:
            port (int): port to search for
            domain (str, optional): domain. Defaults to None.
            ssl (bool, optional): Will set ssl if True. Defaults to None.

        Returns:
            Website: A new or an old website instance with the needed port
        """
        website_name = f"{self.instance_name}_website_{port}"

        website = self.websites.find(website_name)
        if website:
            return website

        website = self.websites.get(website_name)
        ssl = ssl or port == 443  # Use ssl if port is 443 if ssl in not specified

        website.domain = domain
        website.port = port
        website.ssl = ssl

        return website

    def install(self, reset=False):
        """Install required deps for openresty

        Args:
            reset (bool, optional): If true will redo the installation. Defaults to False.
        """
        if reset or self.status == "init":
            # get weblib
            weblibs_path = j.tools.git.ensure_repo(
                "https://github.com/threefoldtech/js-weblibs"  # Place holder repo might be changed
            )

            # copy the templates to the right location
            j.sals.fs.copy_tree(f"{DIR_PATH}/web_resources/", self.path_cfg_dir)

            j.sals.fs.symlink(f"{weblibs_path}/static", f"{self.path_web}/static/weblibs", overwrite=True)
            self.status = Status.INSTALLED

            self.save()

    @property
    def startup_cmd(self):
        pass

    def start(self, reset=False):
        pass

    def stop(self):
        pass

    def is_running(self):
        pass

    def reload(self):
        self.configure()
        j.sals.process.execute("lapis build", cwd=self.path_cfg_dir)

    def cleanup(self):
        j.sals.fs.rmtree(f"{self.path_cfg_dir}/servers")

Ancestors

  • Base
  • types.SimpleNamespace

Instance variables

var logs_dir
Expand source code
@property
def logs_dir(self):
    if not self._logs_dir:
        self._logs_dir = j.sals.fs.join_paths(j.core.dirs.LOGDIR, "openresty", self.instance_name)
        j.sals.fs.mkdirs(self._logs_dir)
    return self._logs_dir
var path_cfg
Expand source code
@property
def path_cfg(self):
    return j.sals.fs.join_paths(self.path_cfg_dir, "nginx.conf")
var path_cfg_dir
Expand source code
@property
def path_cfg_dir(self):
    if not self._path_cfg_dir:
        self._path_cfg_dir = j.sals.fs.join_paths(j.core.dirs.CFGDIR, "nginx", self.instance_name)
        j.sals.fs.mkdirs(self._path_cfg_dir)
    return self._path_cfg_dir
var path_web
Expand source code
@property
def path_web(self):
    if not self._path_web:
        self._path_web = j.sals.fs.join_paths(j.core.dirs.VARDIR, "web", self.instance_name)
        j.sals.fs.mkdirs(j.sals.fs.join_paths(self._path_web, "static"))
    return self._path_web
var startup_cmd
Expand source code
@property
def startup_cmd(self):
    pass
var status

getter method this property

will call _get_value, which would if the value is already defined and will get the default value if not

Returns

any
the field value
Expand source code
def getter(self):
    """
    getter method this property

    will call `_get_value`, which would if the value is already defined
    and will get the default value if not

    Returns:
        any: the field value
    """
    return self._get_value(name, field)
var websites

getter method this property

will call _get_value, which would if the value is already defined and will get the default value if not

Returns

any
the field value
Expand source code
def getter(self):
    """
    getter method this property

    will call `_get_value`, which would if the value is already defined
    and will get the default value if not

    Returns:
        any: the field value
    """
    return self._get_value(name, field)

Methods

def cleanup(self)
Expand source code
def cleanup(self):
    j.sals.fs.rmtree(f"{self.path_cfg_dir}/servers")
def configure(self)

configures main nginx conf

Expand source code
def configure(self):
    """configures main nginx conf"""
    # clean old websites config
    self.cleanup()

    # self.install() This is commented for now until the repo and necessary deps are handled
    configtext = j.tools.jinja2.render_template(
        template_path=j.sals.fs.join_paths(DIR_PATH, "templates", "nginx.conf"), logs_dir=self.logs_dir
    )
    j.sals.fs.write_file(self.path_cfg, configtext)
def get_from_port(self, port, domain=None, ssl=None)

will try to get a website listening on port, if it doesn't exist it will create one

Args

port : int
port to search for
domain : str, optional
domain. Defaults to None.
ssl : bool, optional
Will set ssl if True. Defaults to None.

Returns

Website
A new or an old website instance with the needed port
Expand source code
def get_from_port(self, port, domain=None, ssl=None):
    """will try to get a website listening on port, if it doesn't exist it will create one

    Args:
        port (int): port to search for
        domain (str, optional): domain. Defaults to None.
        ssl (bool, optional): Will set ssl if True. Defaults to None.

    Returns:
        Website: A new or an old website instance with the needed port
    """
    website_name = f"{self.instance_name}_website_{port}"

    website = self.websites.find(website_name)
    if website:
        return website

    website = self.websites.get(website_name)
    ssl = ssl or port == 443  # Use ssl if port is 443 if ssl in not specified

    website.domain = domain
    website.port = port
    website.ssl = ssl

    return website
def install(self, reset=False)

Install required deps for openresty

Args

reset : bool, optional
If true will redo the installation. Defaults to False.
Expand source code
def install(self, reset=False):
    """Install required deps for openresty

    Args:
        reset (bool, optional): If true will redo the installation. Defaults to False.
    """
    if reset or self.status == "init":
        # get weblib
        weblibs_path = j.tools.git.ensure_repo(
            "https://github.com/threefoldtech/js-weblibs"  # Place holder repo might be changed
        )

        # copy the templates to the right location
        j.sals.fs.copy_tree(f"{DIR_PATH}/web_resources/", self.path_cfg_dir)

        j.sals.fs.symlink(f"{weblibs_path}/static", f"{self.path_web}/static/weblibs", overwrite=True)
        self.status = Status.INSTALLED

        self.save()
def is_running(self)
Expand source code
def is_running(self):
    pass
def reload(self)
Expand source code
def reload(self):
    self.configure()
    j.sals.process.execute("lapis build", cwd=self.path_cfg_dir)
def start(self, reset=False)
Expand source code
def start(self, reset=False):
    pass
def stop(self)
Expand source code
def stop(self):
    pass

Inherited members

class Status (value, names=None, *, module=None, qualname=None, type=None, start=1)

An enumeration.

Expand source code
class Status(Enum):
    INIT = "init"
    INSTALLED = "installed"

Ancestors

  • enum.Enum

Class variables

var INIT
var INSTALLED
class Website (parent_=None, instance_name_=None, **values)

A simple attribute-based namespace.

SimpleNamespace(**kwargs)

base class implementation for any class with fields which supports getting/setting raw data for any instance fields.

any instance can have an optional name and a parent.

class Person(Base):
    name = fields.String()
    age = fields.Float()

p = Person(name="ahmed", age="19")
print(p.name, p.age)

Args

parent_ : Base, optional
parent instance. Defaults to None.
instance_name_ : str, optional
instance name. Defaults to None.
**values
any given field values to initiate the instance with
Expand source code
class Website(Base):

    port = fields.Integer(default=80)
    ssl = fields.Boolean()
    domain = fields.String()
    path = fields.String()
    locations = fields.Factory(Location)

    @property
    def path_cfg_dir(self):
        return f"{self.parent.path_cfg_dir}/servers"

    @property
    def path_cfg(self):
        return f"{self.path_cfg_dir}/{self.instance_name}.http.conf"

    @property
    def path_web(self):
        return self.parent.path_web

    def configure(self):
        """Writes configuration of the website and its locations"""

        j.sals.fs.mkdir(self.path_cfg_dir)
        config = render_config_template("website", base_dir=j.core.dirs.BASEDIR, website=self)
        j.sals.fs.write_file(self.path_cfg, config)

        for location_name in self.locations.list_all():
            location = self.locations.get(location_name)
            location.configure()

Ancestors

  • Base
  • types.SimpleNamespace

Instance variables

var domain

getter method this property

will call _get_value, which would if the value is already defined and will get the default value if not

Returns

any
the field value
Expand source code
def getter(self):
    """
    getter method this property

    will call `_get_value`, which would if the value is already defined
    and will get the default value if not

    Returns:
        any: the field value
    """
    return self._get_value(name, field)
var locations

getter method this property

will call _get_value, which would if the value is already defined and will get the default value if not

Returns

any
the field value
Expand source code
def getter(self):
    """
    getter method this property

    will call `_get_value`, which would if the value is already defined
    and will get the default value if not

    Returns:
        any: the field value
    """
    return self._get_value(name, field)
var path

getter method this property

will call _get_value, which would if the value is already defined and will get the default value if not

Returns

any
the field value
Expand source code
def getter(self):
    """
    getter method this property

    will call `_get_value`, which would if the value is already defined
    and will get the default value if not

    Returns:
        any: the field value
    """
    return self._get_value(name, field)
var path_cfg
Expand source code
@property
def path_cfg(self):
    return f"{self.path_cfg_dir}/{self.instance_name}.http.conf"
var path_cfg_dir
Expand source code
@property
def path_cfg_dir(self):
    return f"{self.parent.path_cfg_dir}/servers"
var path_web
Expand source code
@property
def path_web(self):
    return self.parent.path_web
var port

getter method this property

will call _get_value, which would if the value is already defined and will get the default value if not

Returns

any
the field value
Expand source code
def getter(self):
    """
    getter method this property

    will call `_get_value`, which would if the value is already defined
    and will get the default value if not

    Returns:
        any: the field value
    """
    return self._get_value(name, field)
var ssl

getter method this property

will call _get_value, which would if the value is already defined and will get the default value if not

Returns

any
the field value
Expand source code
def getter(self):
    """
    getter method this property

    will call `_get_value`, which would if the value is already defined
    and will get the default value if not

    Returns:
        any: the field value
    """
    return self._get_value(name, field)

Methods

def configure(self)

Writes configuration of the website and its locations

Expand source code
def configure(self):
    """Writes configuration of the website and its locations"""

    j.sals.fs.mkdir(self.path_cfg_dir)
    config = render_config_template("website", base_dir=j.core.dirs.BASEDIR, website=self)
    j.sals.fs.write_file(self.path_cfg, config)

    for location_name in self.locations.list_all():
        location = self.locations.get(location_name)
        location.configure()

Inherited members