diff --git a/platypush/app/_app.py b/platypush/app/_app.py index c11e1af0e..589efb666 100644 --- a/platypush/app/_app.py +++ b/platypush/app/_app.py @@ -42,6 +42,7 @@ class Application: config_file: Optional[str] = None, workdir: Optional[str] = None, logsdir: Optional[str] = None, + cachedir: Optional[str] = None, device_id: Optional[str] = None, pidfile: Optional[str] = None, requests_to_process: Optional[int] = None, @@ -62,6 +63,8 @@ class Application: ``filename`` setting under the ``logging`` section of the configuration file is used. If not set, logging will be sent to stdout and stderr. + :param cachedir: Overrides the ``cachedir`` setting in the configuration + file (default: None). :param device_id: Override the device ID used to identify this instance. If not passed here, it is inferred from the configuration (device_id field). If not present there either, it is inferred from @@ -106,6 +109,9 @@ class Application: self.config_file, device_id=device_id, workdir=os.path.abspath(os.path.expanduser(workdir)) if workdir else None, + cachedir=os.path.abspath(os.path.expanduser(cachedir)) + if cachedir + else None, ctrl_sock=os.path.abspath(os.path.expanduser(ctrl_sock)) if ctrl_sock else None, @@ -206,6 +212,7 @@ class Application: return cls( config_file=opts.config, workdir=opts.workdir, + cachedir=opts.cachedir, logsdir=opts.logsdir, device_id=opts.device_id, pidfile=opts.pidfile, diff --git a/platypush/config/__init__.py b/platypush/config/__init__.py index df09e5f72..eb84184a0 100644 --- a/platypush/config/__init__.py +++ b/platypush/config/__init__.py @@ -56,17 +56,48 @@ class Config: 'now': datetime.datetime.now, } + # Default working directory: + # - $XDG_DATA_HOME/platypush if XDG_DATA_HOME is set + # - /var/lib/platypush if the user is root + # - $HOME/.local/share/platypush otherwise _workdir_location = os.path.join( *( - (os.environ['XDG_DATA_HOME'], 'platypush') + (os.environ['XDG_DATA_HOME'],) if os.environ.get('XDG_DATA_HOME') - else (os.path.expanduser('~'), '.local', 'share', 'platypush') - ) + else ( + (os.sep, 'var', 'lib') + if os.geteuid() == 0 + else (os.path.expanduser('~'), '.local', 'share') + ) + ), + 'platypush', + ) + + # Default cache directory: + # - $XDG_CACHE_DIR/platypush if XDG_CACHE_DIR is set + # - /var/cache/platypush if the user is root + # - $HOME/.cache/platypush otherwise + _cachedir_location = os.path.join( + *( + (os.environ['XDG_CACHE_DIR'],) + if os.environ.get('XDG_CACHE_DIR') + else ( + (os.sep, 'var', 'cache') + if os.geteuid() == 0 + else (os.path.expanduser('~'), '.cache') + ) + ), + 'platypush', ) _included_files: Set[str] = set() - def __init__(self, cfgfile: Optional[str] = None, workdir: Optional[str] = None): + def __init__( + self, + cfgfile: Optional[str] = None, + workdir: Optional[str] = None, + cachedir: Optional[str] = None, + ): """ Constructor. Always use the class as a singleton (i.e. through Config.init), you won't probably need to call the constructor directly @@ -74,6 +105,7 @@ class Config: :param cfgfile: Config file path (default: retrieve the first available location in _cfgfile_locations). :param workdir: Overrides the default working directory. + :param cachedir: Overrides the default cache directory. """ self.backends = {} @@ -91,7 +123,7 @@ class Config: self._config = self._read_config_file(self.config_file) self._init_secrets() - self._init_dirs(workdir=workdir) + self._init_dirs(workdir=workdir, cachedir=cachedir) self._init_db() self._init_logging() self._init_device_id() @@ -168,29 +200,32 @@ class Config: for k, v in self._config['environment'].items(): os.environ[k] = str(v) - def _init_dirs(self, workdir: Optional[str] = None): + def _init_workdir(self, workdir: Optional[str] = None): if workdir: self._config['workdir'] = workdir if not self._config.get('workdir'): self._config['workdir'] = self._workdir_location - self._config['workdir'] = os.path.expanduser( - os.path.expanduser(self._config['workdir']) - ) + self._config['workdir'] = os.path.expanduser(self._config['workdir']) pathlib.Path(self._config['workdir']).mkdir(parents=True, exist_ok=True) + def _init_cachedir(self, cachedir: Optional[str] = None): + if cachedir: + self._config['cachedir'] = cachedir + if not self._config.get('cachedir'): + self._config['cachedir'] = self._cachedir_location + + self._config['cachedir'] = os.path.expanduser(self._config['cachedir']) + pathlib.Path(self._config['cachedir']).mkdir(parents=True, exist_ok=True) + + def _init_scripts_dir(self): + # Create the scripts directory if it doesn't exist if 'scripts_dir' not in self._config: self._config['scripts_dir'] = os.path.join( os.path.dirname(self.config_file), 'scripts' ) os.makedirs(self._config['scripts_dir'], mode=0o755, exist_ok=True) - if 'dashboards_dir' not in self._config: - self._config['dashboards_dir'] = os.path.join( - os.path.dirname(self.config_file), 'dashboards' - ) - os.makedirs(self._config['dashboards_dir'], mode=0o755, exist_ok=True) - # Create a default (empty) __init__.py in the scripts folder init_py = os.path.join(self._config['scripts_dir'], '__init__.py') if not os.path.isfile(init_py): @@ -204,6 +239,19 @@ class Config: ) sys.path = [scripts_parent_dir] + sys.path + def _init_dashboards_dir(self): + if 'dashboards_dir' not in self._config: + self._config['dashboards_dir'] = os.path.join( + os.path.dirname(self.config_file), 'dashboards' + ) + os.makedirs(self._config['dashboards_dir'], mode=0o755, exist_ok=True) + + def _init_dirs(self, workdir: Optional[str] = None, cachedir: Optional[str] = None): + self._init_workdir(workdir=workdir) + self._init_cachedir(cachedir=cachedir) + self._init_scripts_dir() + self._init_dashboards_dir() + def _init_secrets(self): if 'token' in self._config: self._config['token_hash'] = get_hash(self._config['token']) @@ -425,6 +473,7 @@ class Config: cls, cfgfile: Optional[str] = None, workdir: Optional[str] = None, + cachedir: Optional[str] = None, force_reload: bool = False, ) -> "Config": """ @@ -432,7 +481,7 @@ class Config: """ if force_reload or cls._instance is None: cfg_args = [cfgfile] if cfgfile else [] - cls._instance = Config(*cfg_args, workdir=workdir) + cls._instance = Config(*cfg_args, workdir=workdir, cachedir=cachedir) return cls._instance @classmethod @@ -496,6 +545,7 @@ class Config: cfgfile: Optional[str] = None, device_id: Optional[str] = None, workdir: Optional[str] = None, + cachedir: Optional[str] = None, ctrl_sock: Optional[str] = None, **_, ): @@ -505,13 +555,18 @@ class Config: :param cfgfile: Path to the config file (default: _cfgfile_locations) :param device_id: Override the configured device_id. :param workdir: Override the configured working directory. + :param cachedir: Override the configured cache directory. :param ctrl_sock: Override the configured control socket. """ - cfg = cls._get_instance(cfgfile, workdir=workdir, force_reload=True) + cfg = cls._get_instance( + cfgfile, workdir=workdir, cachedir=cachedir, force_reload=True + ) if device_id: cfg.set('device_id', device_id) if workdir: cfg.set('workdir', workdir) + if cachedir: + cfg.set('cachedir', cachedir) if ctrl_sock: cfg.set('ctrl_sock', ctrl_sock) @@ -526,6 +581,15 @@ class Config: assert workdir return workdir # type: ignore + @classmethod + def get_cachedir(cls) -> str: + """ + :return: The path of the configured cache directory. + """ + workdir = cls._get_instance().get('cachedir') + assert workdir + return workdir # type: ignore + @classmethod def get(cls, key: Optional[str] = None, default: Optional[Any] = None): """ diff --git a/platypush/config/config.yaml b/platypush/config/config.yaml index 8cd650846..df1ec68a6 100644 --- a/platypush/config/config.yaml +++ b/platypush/config/config.yaml @@ -55,11 +55,29 @@ # # If not specified, then one of the following will be used: # # # # - $XDG_DATA_HOME/platypush if the XDG_DATA_HOME environment variable is set. +# # - /var/lib/platypush if the user is root. # # - $HOME/.local/share/platypush otherwise. # # workdir: ~/.local/share/platypush ### +### ----------------- +### Cache directory +### ----------------- + +### +# # Note that the cache directory can also be specified at runtime using the +# # --cachedir option. +# # +# # If not specified, then one of the following will be used: +# # +# # - $XDG_CACHE_DIR/platypush if the XDG_CACHE_DIR environment variable is set. +# # - /var/cache/platypush if the user is root. +# # - $HOME/.cache/platypush otherwise. +# +# cachedir: ~/.cache/platypush +### + ### ---------------------- ### Database configuration ### ---------------------- diff --git a/platypush/install/docker/alpine.Dockerfile b/platypush/install/docker/alpine.Dockerfile index 5092f782a..6df50a132 100644 --- a/platypush/install/docker/alpine.Dockerfile +++ b/platypush/install/docker/alpine.Dockerfile @@ -16,8 +16,10 @@ EXPOSE 8008 VOLUME /etc/platypush VOLUME /var/lib/platypush +VOLUME /var/cache/platypush CMD platypush \ --start-redis \ --config /etc/platypush/config.yaml \ - --workdir /var/lib/platypush + --workdir /var/lib/platypush \ + --cachedir /var/cache/platypush diff --git a/platypush/install/docker/debian.Dockerfile b/platypush/install/docker/debian.Dockerfile index 49e59035c..871ec4ab1 100644 --- a/platypush/install/docker/debian.Dockerfile +++ b/platypush/install/docker/debian.Dockerfile @@ -20,8 +20,10 @@ EXPOSE 8008 VOLUME /etc/platypush VOLUME /var/lib/platypush +VOLUME /var/cache/platypush CMD platypush \ --start-redis \ --config /etc/platypush/config.yaml \ - --workdir /var/lib/platypush + --workdir /var/lib/platypush \ + --cachedir /var/cache/platypush diff --git a/platypush/install/docker/fedora.Dockerfile b/platypush/install/docker/fedora.Dockerfile index d355f8d72..98be6fb02 100644 --- a/platypush/install/docker/fedora.Dockerfile +++ b/platypush/install/docker/fedora.Dockerfile @@ -19,8 +19,10 @@ EXPOSE 8008 VOLUME /etc/platypush VOLUME /var/lib/platypush +VOLUME /var/cache/platypush CMD platypush \ --start-redis \ --config /etc/platypush/config.yaml \ - --workdir /var/lib/platypush + --workdir /var/lib/platypush \ + --cachedir /var/cache/platypush diff --git a/platypush/install/docker/ubuntu.Dockerfile b/platypush/install/docker/ubuntu.Dockerfile index 14b400802..cacd7b3e7 100644 --- a/platypush/install/docker/ubuntu.Dockerfile +++ b/platypush/install/docker/ubuntu.Dockerfile @@ -20,8 +20,10 @@ EXPOSE 8008 VOLUME /etc/platypush VOLUME /var/lib/platypush +VOLUME /var/cache/platypush CMD platypush \ --start-redis \ --config /etc/platypush/config.yaml \ - --workdir /var/lib/platypush + --workdir /var/lib/platypush \ + --cachedir /var/cache/platypush