mirror of
https://github.com/YunoHost/moulinette.git
synced 2024-09-03 20:06:31 +02:00
We don't need no namespaces ... but let's it customizable through a var env if needed...
This commit is contained in:
parent
1849d1aa3b
commit
c750226a3b
3 changed files with 43 additions and 53 deletions
|
@ -72,13 +72,12 @@ def init(logging_config=None, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
# Easy access to interfaces
|
# Easy access to interfaces
|
||||||
def api(namespaces, host="localhost", port=80, routes={}):
|
def api(host="localhost", port=80, routes={}):
|
||||||
"""Web server (API) interface
|
"""Web server (API) interface
|
||||||
|
|
||||||
Run a HTTP server with the moulinette for an API usage.
|
Run a HTTP server with the moulinette for an API usage.
|
||||||
|
|
||||||
Keyword arguments:
|
Keyword arguments:
|
||||||
- namespaces -- The list of namespaces to use
|
|
||||||
- host -- Server address to bind to
|
- host -- Server address to bind to
|
||||||
- port -- Server port to bind to
|
- port -- Server port to bind to
|
||||||
- routes -- A dict of additional routes to add in the form of
|
- routes -- A dict of additional routes to add in the form of
|
||||||
|
@ -88,31 +87,27 @@ def api(namespaces, host="localhost", port=80, routes={}):
|
||||||
from moulinette.actionsmap import ActionsMap
|
from moulinette.actionsmap import ActionsMap
|
||||||
from moulinette.interfaces.api import Interface, ActionsMapParser
|
from moulinette.interfaces.api import Interface, ActionsMapParser
|
||||||
try:
|
try:
|
||||||
actionsmap = ActionsMap(ActionsMapParser(),
|
actionsmap = ActionsMap(ActionsMapParser())
|
||||||
namespaces=namespaces)
|
|
||||||
interface = Interface(actionsmap=actionsmap,
|
interface = Interface(actionsmap=actionsmap,
|
||||||
routes=routes)
|
routes=routes)
|
||||||
interface.run(host, port)
|
interface.run(host, port)
|
||||||
except MoulinetteError as e:
|
except MoulinetteError as e:
|
||||||
import logging
|
import logging
|
||||||
|
logging.getLogger().error(e.strerror)
|
||||||
logging.getLogger(namespaces[0]).error(e.strerror)
|
return 1
|
||||||
return e.errno if hasattr(e, "errno") else 1
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
import logging
|
import logging
|
||||||
|
logging.getLogger().info(m18n.g("operation_interrupted"))
|
||||||
logging.getLogger(namespaces[0]).info(m18n.g("operation_interrupted"))
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def cli(namespaces, args, top_parser, output_as=None, timeout=None):
|
def cli(args, top_parser, output_as=None, timeout=None):
|
||||||
"""Command line interface
|
"""Command line interface
|
||||||
|
|
||||||
Execute an action with the moulinette from the CLI and print its
|
Execute an action with the moulinette from the CLI and print its
|
||||||
result in a readable format.
|
result in a readable format.
|
||||||
|
|
||||||
Keyword arguments:
|
Keyword arguments:
|
||||||
- namespaces -- The list of namespaces to use
|
|
||||||
- args -- A list of argument strings
|
- args -- A list of argument strings
|
||||||
- output_as -- Output result in another format, see
|
- output_as -- Output result in another format, see
|
||||||
moulinette.interfaces.cli.Interface for possible values
|
moulinette.interfaces.cli.Interface for possible values
|
||||||
|
@ -122,14 +117,12 @@ def cli(namespaces, args, top_parser, output_as=None, timeout=None):
|
||||||
from moulinette.actionsmap import ActionsMap
|
from moulinette.actionsmap import ActionsMap
|
||||||
from moulinette.interfaces.cli import Interface, ActionsMapParser
|
from moulinette.interfaces.cli import Interface, ActionsMapParser
|
||||||
try:
|
try:
|
||||||
actionsmap = ActionsMap(ActionsMapParser(top_parser=top_parser),
|
actionsmap = ActionsMap(ActionsMapParser(top_parser=top_parser))
|
||||||
namespaces=namespaces)
|
|
||||||
interface = Interface(actionsmap=actionsmap)
|
interface = Interface(actionsmap=actionsmap)
|
||||||
interface.run(args, output_as=output_as, timeout=timeout)
|
interface.run(args, output_as=output_as, timeout=timeout)
|
||||||
except MoulinetteError as e:
|
except MoulinetteError as e:
|
||||||
import logging
|
import logging
|
||||||
|
logging.getLogger().error(e.strerror)
|
||||||
logging.getLogger(namespaces[0]).error(e.strerror)
|
|
||||||
return 1
|
return 1
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import os
|
||||||
import re
|
import re
|
||||||
import logging
|
import logging
|
||||||
import yaml
|
import yaml
|
||||||
|
import glob
|
||||||
import cPickle as pickle
|
import cPickle as pickle
|
||||||
from time import time
|
from time import time
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
@ -398,16 +399,14 @@ class ActionsMap(object):
|
||||||
Moreover, the action can have specific argument(s).
|
Moreover, the action can have specific argument(s).
|
||||||
|
|
||||||
This class allows to manipulate one or several actions maps
|
This class allows to manipulate one or several actions maps
|
||||||
associated to a namespace. If no namespace is given, it will load
|
associated to a namespace.
|
||||||
all available namespaces.
|
|
||||||
|
|
||||||
Keyword arguments:
|
Keyword arguments:
|
||||||
- top_parser -- A BaseActionsMapParser-derived instance to use for
|
- top_parser -- A BaseActionsMapParser-derived instance to use for
|
||||||
parsing the actions map
|
parsing the actions map
|
||||||
- namespaces -- The list of namespaces to use
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, top_parser, namespaces=[]):
|
def __init__(self, top_parser):
|
||||||
|
|
||||||
assert isinstance(top_parser, BaseActionsMapParser), "Invalid parser class '%s'" % top_parser.__class__.__name__
|
assert isinstance(top_parser, BaseActionsMapParser), "Invalid parser class '%s'" % top_parser.__class__.__name__
|
||||||
|
|
||||||
|
@ -415,12 +414,10 @@ class ActionsMap(object):
|
||||||
DATA_DIR = moulinette_env["DATA_DIR"]
|
DATA_DIR = moulinette_env["DATA_DIR"]
|
||||||
CACHE_DIR = moulinette_env["CACHE_DIR"]
|
CACHE_DIR = moulinette_env["CACHE_DIR"]
|
||||||
|
|
||||||
if len(namespaces) == 0:
|
|
||||||
namespaces = self.get_namespaces()
|
|
||||||
actionsmaps = OrderedDict()
|
actionsmaps = OrderedDict()
|
||||||
|
|
||||||
# Iterate over actions map namespaces
|
# Iterate over actions map namespaces
|
||||||
for n in namespaces:
|
for n in self.get_namespaces():
|
||||||
logger.debug("loading actions map namespace '%s'", n)
|
logger.debug("loading actions map namespace '%s'", n)
|
||||||
|
|
||||||
actionsmap_yml = "%s/actionsmap/%s.yml" % (DATA_DIR, n)
|
actionsmap_yml = "%s/actionsmap/%s.yml" % (DATA_DIR, n)
|
||||||
|
@ -441,10 +438,10 @@ class ActionsMap(object):
|
||||||
# TODO: Switch to python3 and catch proper exception
|
# TODO: Switch to python3 and catch proper exception
|
||||||
except (IOError, EOFError):
|
except (IOError, EOFError):
|
||||||
self.from_cache = False
|
self.from_cache = False
|
||||||
actionsmaps = self.generate_cache(namespaces)
|
actionsmaps[n] = self.generate_cache(n)
|
||||||
else: # cache file doesn't exists
|
else: # cache file doesn't exists
|
||||||
self.from_cache = False
|
self.from_cache = False
|
||||||
actionsmaps = self.generate_cache(namespaces)
|
actionsmaps[n] = self.generate_cache(n)
|
||||||
|
|
||||||
# Load translations
|
# Load translations
|
||||||
m18n.load_namespace(n)
|
m18n.load_namespace(n)
|
||||||
|
@ -587,56 +584,55 @@ class ActionsMap(object):
|
||||||
moulinette_env = init_moulinette_env()
|
moulinette_env = init_moulinette_env()
|
||||||
DATA_DIR = moulinette_env["DATA_DIR"]
|
DATA_DIR = moulinette_env["DATA_DIR"]
|
||||||
|
|
||||||
for f in os.listdir("%s/actionsmap" % DATA_DIR):
|
# This var is ['*'] by default but could be set for example to
|
||||||
if f.endswith(".yml"):
|
# ['yunohost', 'yml_*']
|
||||||
namespaces.append(f[:-4])
|
NAMESPACE_PATTERNS = moulinette_env["NAMESPACES"]
|
||||||
|
|
||||||
|
# Look for all files that match the given patterns in the actionsmap dir
|
||||||
|
for namespace_pattern in NAMESPACE_PATTERNS:
|
||||||
|
namespaces.extend(glob.glob("%s/actionsmap/%s.yml" % (DATA_DIR, namespace_pattern)))
|
||||||
|
|
||||||
|
# Keep only the filenames with extension
|
||||||
|
namespaces = [os.path.basename(n)[:-4] for n in namespaces]
|
||||||
|
|
||||||
return namespaces
|
return namespaces
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_cache(klass, namespaces=None):
|
def generate_cache(klass, namespace):
|
||||||
"""
|
"""
|
||||||
Generate cache for the actions map's file(s)
|
Generate cache for the actions map's file(s)
|
||||||
|
|
||||||
Keyword arguments:
|
Keyword arguments:
|
||||||
- namespaces -- A list of namespaces to generate cache for
|
- namespace -- The namespace to generate cache for
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A dict of actions map for each namespaces
|
The action map for the namespace
|
||||||
|
|
||||||
"""
|
"""
|
||||||
moulinette_env = init_moulinette_env()
|
moulinette_env = init_moulinette_env()
|
||||||
CACHE_DIR = moulinette_env["CACHE_DIR"]
|
CACHE_DIR = moulinette_env["CACHE_DIR"]
|
||||||
DATA_DIR = moulinette_env["DATA_DIR"]
|
DATA_DIR = moulinette_env["DATA_DIR"]
|
||||||
|
|
||||||
actionsmaps = {}
|
|
||||||
if not namespaces:
|
|
||||||
namespaces = klass.get_namespaces()
|
|
||||||
|
|
||||||
# Iterate over actions map namespaces
|
# Iterate over actions map namespaces
|
||||||
for n in namespaces:
|
logger.debug("generating cache for actions map namespace '%s'", namespace)
|
||||||
logger.debug("generating cache for actions map namespace '%s'", n)
|
|
||||||
|
|
||||||
# Read actions map from yaml file
|
# Read actions map from yaml file
|
||||||
am_file = "%s/actionsmap/%s.yml" % (DATA_DIR, n)
|
am_file = "%s/actionsmap/%s.yml" % (DATA_DIR, namespace)
|
||||||
with open(am_file, "r") as f:
|
with open(am_file, "r") as f:
|
||||||
actionsmaps[n] = ordered_yaml_load(f)
|
actionsmap = ordered_yaml_load(f)
|
||||||
|
|
||||||
# at installation, cachedir might not exists
|
# at installation, cachedir might not exists
|
||||||
if os.path.exists("%s/actionsmap/" % CACHE_DIR):
|
for old_cache in glob.glob("%s/actionsmap/%s-*.pkl" % (CACHE_DIR, namespace)):
|
||||||
# clean old cached files
|
os.remove(old_cache)
|
||||||
for i in os.listdir("%s/actionsmap/" % CACHE_DIR):
|
|
||||||
if i.endswith(".pkl"):
|
|
||||||
os.remove("%s/actionsmap/%s" % (CACHE_DIR, i))
|
|
||||||
|
|
||||||
# Cache actions map into pickle file
|
# Cache actions map into pickle file
|
||||||
am_file_stat = os.stat(am_file)
|
am_file_stat = os.stat(am_file)
|
||||||
|
|
||||||
pkl = "%s-%d-%d.pkl" % (n, am_file_stat.st_size, am_file_stat.st_mtime)
|
pkl = "%s-%d-%d.pkl" % (namespace, am_file_stat.st_size, am_file_stat.st_mtime)
|
||||||
|
|
||||||
with open_cachefile(pkl, "w", subdir="actionsmap") as f:
|
with open_cachefile(pkl, "w", subdir="actionsmap") as f:
|
||||||
pickle.dump(actionsmaps[n], f)
|
pickle.dump(actionsmap, f)
|
||||||
|
|
||||||
return actionsmaps
|
return actionsmap
|
||||||
|
|
||||||
# Private methods
|
# Private methods
|
||||||
|
|
||||||
|
|
|
@ -11,4 +11,5 @@ def init_moulinette_env():
|
||||||
"MOULINETTE_LOCALES_DIR", "/usr/share/moulinette/locale"
|
"MOULINETTE_LOCALES_DIR", "/usr/share/moulinette/locale"
|
||||||
),
|
),
|
||||||
"CACHE_DIR": environ.get("MOULINETTE_CACHE_DIR", "/var/cache/moulinette"),
|
"CACHE_DIR": environ.get("MOULINETTE_CACHE_DIR", "/var/cache/moulinette"),
|
||||||
|
"NAMESPACES": environ.get("MOULINETTE_NAMESPACES", "*").split(), # By default we'll load every namespace we find
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue