diff --git a/ara/config.py b/ara/config.py
deleted file mode 100644
index e8d7587d..00000000
--- a/ara/config.py
+++ /dev/null
@@ -1,171 +0,0 @@
-# Copyright (c) 2017 Red Hat, Inc.
-#
-# This file is part of ARA: Ansible Run Analysis.
-#
-# ARA is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# ARA is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with ARA. If not, see .
-
-import os
-import xstatic.main
-import xstatic.pkg.bootstrap_scss
-import xstatic.pkg.datatables
-import xstatic.pkg.jquery
-import xstatic.pkg.patternfly
-import xstatic.pkg.patternfly_bootstrap_treeview
-
-from ansible import __version__ as ansible_version
-from ansible.constants import get_config
-try:
- from ansible.constants import load_config_file
-except ImportError:
- # Ansible 2.4 no longer provides load_config_file, this is handled further
- # down
- from ansible.config.manager import find_ini_config_file
- # Also, don't scream deprecated things at us
- import ansible.constants
- ansible.constants._deprecated = lambda *args: None
-from distutils.version import LooseVersion
-from six.moves import configparser
-
-
-def _ara_config(config, key, env_var, default=None, section='ara',
- value_type=None):
- """
- Wrapper around Ansible's get_config backward/forward compatibility
- """
- if default is None:
- try:
- # We're using env_var as keys in the DEFAULTS dict
- default = DEFAULTS.get(env_var)
- except KeyError as e:
- msg = 'There is no default value for {0}: {1}'.format(key, str(e))
- raise KeyError(msg)
-
- # >= 2.3.0.0 (NOTE: Ansible trunk versioning scheme has 3 digits, not 4)
- if LooseVersion(ansible_version) >= LooseVersion('2.3.0'):
- return get_config(config, section, key, env_var, default,
- value_type=value_type)
-
- # < 2.3.0.0 compatibility
- if value_type is None:
- return get_config(config, section, key, env_var, default)
-
- args = {
- 'boolean': dict(boolean=True),
- 'integer': dict(integer=True),
- 'list': dict(islist=True),
- 'tmppath': dict(istmppath=True)
- }
- return get_config(config, section, key, env_var, default,
- **args[value_type])
-
-
-DEFAULTS = {
- 'ARA_AUTOCREATE_DATABASE': True,
- 'ARA_DIR': os.path.expanduser('~/.ara'),
- 'ARA_ENABLE_DEBUG_VIEW': False,
- 'ARA_HOST': '127.0.0.1',
- 'ARA_IGNORE_EMPTY_GENERATION': True,
- 'ARA_IGNORE_MIMETYPE_WARNINGS': True,
- 'ARA_IGNORE_PARAMETERS': ['extra_vars'],
- 'ARA_LOG_CONFIG': None,
- 'ARA_LOG_FORMAT': '%(asctime)s - %(name)s - %(levelname)s - %(message)s',
- 'ARA_LOG_LEVEL': 'INFO',
- 'ARA_PATH_MAX': 40,
- 'ARA_PLAYBOOK_OVERRIDE': None,
- 'ARA_PLAYBOOK_PER_PAGE': 10,
- 'ARA_PORT': '9191',
- 'ARA_RESULT_PER_PAGE': 25,
- 'ARA_SQL_DEBUG': False,
- 'ARA_TMP_DIR': os.path.expanduser('~/.ansible/tmp')
-}
-
-# Bootstrap Ansible configuration
-# Ansible >=2.4 takes care of loading the configuration file itself
-if LooseVersion(ansible_version) < LooseVersion('2.4.0'):
- config, path = load_config_file()
-else:
- path = find_ini_config_file()
- config = configparser.ConfigParser()
- if path is not None:
- config.read(path)
-
-# Some defaults need to be based on top of a "processed" ARA_DIR
-ARA_DIR = _ara_config(config, 'dir', 'ARA_DIR')
-database_path = os.path.join(ARA_DIR, 'ansible.sqlite')
-DEFAULTS.update({
- 'ARA_LOG_FILE': os.path.join(ARA_DIR, 'ara.log'),
- 'ARA_DATABASE': 'sqlite:///{}'.format(database_path)
-})
-
-ARA_AUTOCREATE_DATABASE = _ara_config(config, 'autocreate_database',
- 'ARA_AUTOCREATE_DATABASE',
- value_type='boolean')
-ARA_ENABLE_DEBUG_VIEW = _ara_config(config, 'enable_debug_view',
- 'ARA_ENABLE_DEBUG_VIEW',
- value_type='boolean')
-ARA_HOST = _ara_config(config, 'host', 'ARA_HOST')
-ARA_IGNORE_PARAMETERS = _ara_config(config, 'ignore_parameters',
- 'ARA_IGNORE_PARAMETERS',
- value_type='list')
-ARA_LOG_CONFIG = _ara_config(config, 'logconfig', 'ARA_LOG_CONFIG')
-ARA_LOG_FILE = _ara_config(config, 'logfile', 'ARA_LOG_FILE')
-ARA_LOG_FORMAT = _ara_config(config, 'logformat', 'ARA_LOG_FORMAT')
-ARA_LOG_LEVEL = _ara_config(config, 'loglevel', 'ARA_LOG_LEVEL')
-ARA_PLAYBOOK_OVERRIDE = _ara_config(config, 'playbook_override',
- 'ARA_PLAYBOOK_OVERRIDE',
- value_type='list')
-ARA_PLAYBOOK_PER_PAGE = _ara_config(config, 'playbook_per_page',
- 'ARA_PLAYBOOK_PER_PAGE',
- value_type='integer')
-ARA_PORT = _ara_config(config, 'port', 'ARA_PORT')
-ARA_RESULT_PER_PAGE = _ara_config(config, 'result_per_page',
- 'ARA_RESULT_PER_PAGE',
- value_type='integer')
-ARA_TMP_DIR = _ara_config(config, 'local_tmp', 'ANSIBLE_LOCAL_TEMP',
- default=DEFAULTS['ARA_TMP_DIR'],
- section='defaults',
- value_type='tmppath')
-
-# Static generation with flask-frozen
-ARA_IGNORE_EMPTY_GENERATION = _ara_config(config,
- 'ignore_empty_generation',
- 'ARA_IGNORE_EMPTY_GENERATION',
- value_type='boolean')
-FREEZER_DEFAULT_MIMETYPE = 'text/html'
-FREEZER_IGNORE_MIMETYPE_WARNINGS = _ara_config(config,
- 'ignore_mimetype_warnings',
- 'ARA_IGNORE_MIMETYPE_WARNINGS',
- value_type='boolean')
-FREEZER_RELATIVE_URLS = True
-FREEZER_IGNORE_404_NOT_FOUND = True
-
-# SQLAlchemy/Alembic settings
-SQLALCHEMY_DATABASE_URI = _ara_config(config, 'database', 'ARA_DATABASE')
-SQLALCHEMY_ECHO = _ara_config(config, 'sqldebug',
- 'ARA_SQL_DEBUG',
- value_type='boolean')
-SQLALCHEMY_TRACK_MODIFICATIONS = False
-
-INSTALL_PATH = os.path.dirname(os.path.realpath(__file__))
-DB_MIGRATIONS = os.path.join(INSTALL_PATH, 'db')
-
-# Xstatic configuration
-treeview = xstatic.pkg.patternfly_bootstrap_treeview
-XSTATIC = dict(
- bootstrap=xstatic.main.XStatic(xstatic.pkg.bootstrap_scss).base_dir,
- datatables=xstatic.main.XStatic(xstatic.pkg.datatables).base_dir,
- jquery=xstatic.main.XStatic(xstatic.pkg.jquery).base_dir,
- patternfly=xstatic.main.XStatic(xstatic.pkg.patternfly).base_dir,
- patternfly_bootstrap_treeview=xstatic.main.XStatic(treeview).base_dir,
-)
diff --git a/ara/plugins/modules/__init__.py b/ara/config/__init__.py
similarity index 100%
rename from ara/plugins/modules/__init__.py
rename to ara/config/__init__.py
diff --git a/ara/config/base.py b/ara/config/base.py
new file mode 100644
index 00000000..c5986335
--- /dev/null
+++ b/ara/config/base.py
@@ -0,0 +1,79 @@
+# Copyright (c) 2017 Red Hat, Inc.
+#
+# This file is part of ARA: Ansible Run Analysis.
+#
+# ARA is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# ARA is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with ARA. If not, see .
+
+import os
+from ara.config.compat import ara_config
+from ara.setup import path as ara_location
+
+
+class BaseConfig(object):
+ def __init__(self):
+ self.ARA_DIR = ara_config(
+ 'dir',
+ 'ARA_DIR',
+ os.path.expanduser('~/.ara')
+ )
+ database_path = os.path.join(self.ARA_DIR, 'ansible.sqlite')
+ self.ARA_DATABASE = ara_config(
+ 'database',
+ 'ARA_DATABASE',
+ 'sqlite:///%s' % database_path
+ )
+ self.ARA_AUTOCREATE_DATABASE = ara_config(
+ 'autocreate_database',
+ 'ARA_AUTOCREATE_DATABASE',
+ True,
+ value_type='boolean'
+ )
+ self.SQLALCHEMY_DATABASE_URI = self.ARA_DATABASE
+ self.SQLALCHEMY_TRACK_MODIFICATIONS = False
+ self.DB_MIGRATIONS = os.path.join(ara_location, 'db')
+
+ self.ARA_HOST = ara_config('host', 'ARA_HOST', '127.0.0.1')
+ self.ARA_PORT = ara_config('port', 'ARA_PORT', '9191')
+ self.ARA_IGNORE_PARAMETERS = ara_config(
+ 'ignore_parameters',
+ 'ARA_IGNORE_PARAMETERS',
+ ['extra_vars'],
+ value_type='list'
+ )
+
+ # Static generation with flask-frozen
+ self.ARA_IGNORE_EMPTY_GENERATION = ara_config(
+ 'ignore_empty_generation',
+ 'ARA_IGNORE_EMPTY_GENERATION',
+ True,
+ value_type='boolean'
+ )
+ self.FREEZER_DEFAULT_MIMETYPE = 'text/html'
+ self.FREEZER_IGNORE_MIMETYPE_WARNINGS = ara_config(
+ 'ignore_mimetype_warnings',
+ 'ARA_IGNORE_MIMETYPE_WARNINGS',
+ True,
+ value_type='boolean'
+ )
+ self.FREEZER_RELATIVE_URLS = True
+ self.FREEZER_IGNORE_404_NOT_FOUND = True
+
+ @property
+ def config(self):
+ """ Returns a dictionary for the loaded configuration """
+ return {
+ key: self.__dict__[key]
+ for key in dir(self)
+ if key.isupper()
+ }
diff --git a/ara/config/compat.py b/ara/config/compat.py
new file mode 100644
index 00000000..0708aaca
--- /dev/null
+++ b/ara/config/compat.py
@@ -0,0 +1,65 @@
+# Copyright (c) 2017 Red Hat, Inc.
+#
+# This file is part of ARA: Ansible Run Analysis.
+#
+# ARA is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# ARA is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with ARA. If not, see .
+
+# Compatibility layer between ARA and the different version of Ansible
+
+from ansible import __version__ as ansible_version
+from ansible.constants import get_config
+try:
+ from ansible.constants import load_config_file
+except ImportError:
+ # Ansible 2.4 no longer provides load_config_file, this is handled further
+ # down
+ from ansible.config.manager import find_ini_config_file
+ # Also, don't scream deprecated things at us
+ import ansible.constants
+ ansible.constants._deprecated = lambda *args: None
+from distutils.version import LooseVersion
+from six.moves import configparser
+
+
+def ara_config(key, env_var, default, section='ara', value_type=None):
+ """
+ Wrapper around Ansible's get_config backward/forward compatibility
+ """
+ # Bootstrap Ansible configuration
+ # Ansible >=2.4 takes care of loading the configuration file itself
+ if LooseVersion(ansible_version) < LooseVersion('2.4.0'):
+ config, path = load_config_file()
+ else:
+ path = find_ini_config_file()
+ config = configparser.ConfigParser()
+ if path is not None:
+ config.read(path)
+
+ # >= 2.3.0.0 (NOTE: Ansible trunk versioning scheme has 3 digits, not 4)
+ if LooseVersion(ansible_version) >= LooseVersion('2.3.0'):
+ return get_config(config, section, key, env_var, default,
+ value_type=value_type)
+
+ # < 2.3.0.0 compatibility
+ if value_type is None:
+ return get_config(config, section, key, env_var, default)
+
+ args = {
+ 'boolean': dict(boolean=True),
+ 'integer': dict(integer=True),
+ 'list': dict(islist=True),
+ 'tmppath': dict(istmppath=True)
+ }
+ return get_config(config, section, key, env_var, default,
+ **args[value_type])
diff --git a/ara/config/logger.py b/ara/config/logger.py
new file mode 100644
index 00000000..23759e90
--- /dev/null
+++ b/ara/config/logger.py
@@ -0,0 +1,142 @@
+# Copyright (c) 2017 Red Hat, Inc.
+#
+# This file is part of ARA: Ansible Run Analysis.
+#
+# ARA is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# ARA is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with ARA. If not, see .
+
+# Note: This file tries to import itself if it's named logging, thus, logger.
+
+import logging
+import logging.config
+import os
+import yaml
+from ara.config.compat import ara_config
+
+
+DEFAULT_LOG_CONFIG = """
+---
+version: 1
+formatters:
+ normal:
+ format: '%(asctime)s %(levelname)s %(name)s: %(message)s'
+ console:
+ format: '%(asctime)s %(levelname)s %(name)s: %(message)s'
+handlers:
+ console:
+ class: logging.StreamHandler
+ formatter: console
+ level: INFO
+ stream: ext://sys.stdout
+ normal:
+ class: logging.handlers.TimedRotatingFileHandler
+ formatter: normal
+ level: DEBUG
+ filename: '{dir}/{file}'
+ when: 'midnight'
+ interval: 1
+ backupCount: 30
+loggers:
+ ara:
+ handlers:
+ - console
+ - normal
+ level: {level}
+ propagate: 0
+ alembic:
+ handlers:
+ - console
+ - normal
+ level: WARN
+ propagate: 0
+ sqlalchemy.engine:
+ handlers:
+ - console
+ - normal
+ level: WARN
+ propagate: 0
+ werkzeug:
+ handlers:
+ - console
+ - normal
+ level: INFO
+ propagate: 0
+root:
+ handlers:
+ - normal
+ level: {level}
+"""
+
+
+class LogConfig(object):
+ def __init__(self):
+ default_dir = ara_config('dir', 'ARA_DIR',
+ os.path.expanduser('~/.ara'))
+ self.ARA_LOG_CONFIG = ara_config(
+ 'logconfig', 'ARA_LOG_CONFIG', os.path.join(default_dir,
+ 'logging.yml')
+ )
+ self.ARA_LOG_DIR = ara_config('logdir', 'ARA_LOG_DIR', default_dir)
+ self.ARA_LOG_FILE = ara_config('logfile', 'ARA_LOG_FILE', 'ara.log')
+ self.ARA_LOG_LEVEL = ara_config('loglevel', 'ARA_LOG_LEVEL', 'INFO')
+ if self.ARA_LOG_LEVEL == 'DEBUG':
+ self.SQLALCHEMY_ECHO = True
+ self.ARA_ENABLE_DEBUG_VIEW = True
+ else:
+ self.SQLALCHEMY_ECHO = False
+ self.ARA_ENABLE_DEBUG_VIEW = False
+
+ @property
+ def config(self):
+ """ Returns a dictionary for the loaded configuration """
+ return {
+ key: self.__dict__[key]
+ for key in dir(self)
+ if key.isupper()
+ }
+
+
+def setup_logging(config=None):
+ if config is None:
+ config = LogConfig().config
+
+ if not os.path.isdir(config['ARA_LOG_DIR']):
+ os.makedirs(config['ARA_LOG_DIR'], mode=0o750)
+
+ if not os.path.exists(config['ARA_LOG_CONFIG']):
+ default_config = DEFAULT_LOG_CONFIG.format(
+ dir=config['ARA_LOG_DIR'],
+ file=config['ARA_LOG_FILE'],
+ level=config['ARA_LOG_LEVEL']
+ )
+ with open(config['ARA_LOG_CONFIG'], 'w') as log_config:
+ log_config.write(default_config.lstrip())
+
+ ext = os.path.splitext(config['ARA_LOG_CONFIG'])[1]
+ if ext in ('.yml', '.yaml', '.json'):
+ # yaml.safe_load can load json as well as yaml
+ logging.config.dictConfig(yaml.safe_load(
+ open(config['ARA_LOG_CONFIG'], 'r')
+ ))
+ else:
+ logging.config.fileConfig(config['ARA_LOG_CONFIG'])
+
+ logger = logging.getLogger('ara.logging')
+ msg = 'Logging: Level {level} from {config}, logging to {dir}/{file}'
+ msg = msg.format(
+ level=config['ARA_LOG_LEVEL'],
+ config=config['ARA_LOG_CONFIG'],
+ dir=config['ARA_LOG_DIR'],
+ file=config['ARA_LOG_FILE'],
+ )
+ logger.debug(msg)
diff --git a/ara/config/webapp.py b/ara/config/webapp.py
new file mode 100644
index 00000000..57c4f3cf
--- /dev/null
+++ b/ara/config/webapp.py
@@ -0,0 +1,64 @@
+# Copyright (c) 2017 Red Hat, Inc.
+#
+# This file is part of ARA: Ansible Run Analysis.
+#
+# ARA is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# ARA is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with ARA. If not, see .
+
+from xstatic import main as xs
+import xstatic.pkg.bootstrap_scss
+import xstatic.pkg.datatables
+import xstatic.pkg.jquery
+import xstatic.pkg.patternfly
+import xstatic.pkg.patternfly_bootstrap_treeview
+from ara.config.compat import ara_config
+
+
+class WebAppConfig(object):
+ def __init__(self):
+ self.ARA_PLAYBOOK_PER_PAGE = ara_config(
+ 'playbook_per_page',
+ 'ARA_PLAYBOOK_PER_PAGE',
+ 10,
+ value_type='integer'
+ )
+ self.ARA_RESULT_PER_PAGE = ara_config(
+ 'result_per_page',
+ 'ARA_RESULT_PER_PAGE',
+ 25,
+ value_type='integer'
+ )
+ self.ARA_PLAYBOOK_OVERRIDE = ara_config(
+ 'playbook_override',
+ 'ARA_PLAYBOOK_OVERRIDE',
+ None,
+ value_type='list'
+ )
+
+ treeview = xstatic.pkg.patternfly_bootstrap_treeview
+ self.XSTATIC = dict(
+ bootstrap=xs.XStatic(xstatic.pkg.bootstrap_scss).base_dir,
+ datatables=xs.XStatic(xstatic.pkg.datatables).base_dir,
+ jquery=xs.XStatic(xstatic.pkg.jquery).base_dir,
+ patternfly=xs.XStatic(xstatic.pkg.patternfly).base_dir,
+ patternfly_bootstrap_treeview=xs.XStatic(treeview).base_dir,
+ )
+
+ @property
+ def config(self):
+ """ Returns a dictionary for the loaded configuration """
+ return {
+ key: self.__dict__[key]
+ for key in dir(self)
+ if key.isupper()
+ }
diff --git a/ara/context_processors.py b/ara/context_processors.py
deleted file mode 100644
index a223e96a..00000000
--- a/ara/context_processors.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright (c) 2017 Red Hat, Inc.
-#
-# This file is part of ARA: Ansible Run Analysis.
-#
-# ARA is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# ARA is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with ARA. If not, see .
-
-import sys
-
-from ansible import __version__ as ansible_version
-from ara import __release__ as ara_release
-from ara import models
-
-
-def configure_context_processors(app):
- @app.context_processor
- def ctx_add_nav_data():
- """
- Returns standard data that will be available in every template view.
- """
- try:
- models.Playbook.query.one()
- empty_database = False
- except models.MultipleResultsFound:
- empty_database = False
- except models.NoResultFound:
- empty_database = True
-
- # Get python version info
- major, minor, micro, release, serial = sys.version_info
-
- return dict(ara_version=ara_release,
- ansible_version=ansible_version,
- python_version="{0}.{1}".format(major, minor),
- empty_database=empty_database)
diff --git a/ara/errorhandlers.py b/ara/errorhandlers.py
deleted file mode 100644
index 47773a9f..00000000
--- a/ara/errorhandlers.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (c) 2017 Red Hat, Inc.
-#
-# This file is part of ARA: Ansible Run Analysis.
-#
-# ARA is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# ARA is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with ARA. If not, see .
-
-from flask import render_template
-
-
-def configure_errorhandlers(app):
- @app.errorhandler(404)
- def page_not_found(error):
- return render_template('errors/404.html', error=error), 404
diff --git a/ara/filters.py b/ara/filters.py
deleted file mode 100644
index 80a29cca..00000000
--- a/ara/filters.py
+++ /dev/null
@@ -1,122 +0,0 @@
-# Copyright (c) 2017 Red Hat, Inc.
-#
-# This file is part of ARA: Ansible Run Analysis.
-#
-# ARA is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# ARA is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with ARA. If not, see .
-
-import datetime
-import logging
-import six
-
-from ara.utils import fast_count
-from ara.utils import playbook_treeview
-from jinja2 import Markup
-from os import path
-from oslo_serialization import jsonutils
-from pygments import highlight
-from pygments.formatters import HtmlFormatter
-from pygments.lexers import YamlLexer
-from pygments.lexers import JsonLexer
-from pygments.lexers.special import TextLexer
-
-
-def configure_template_filters(app):
- log = logging.getLogger('%s.filters' % app.logger_name)
-
- @app.template_filter('datefmt')
- def jinja_date_formatter(timestamp, format='%Y-%m-%d %H:%M:%S'):
- """ Reformats a datetime timestamp from str(datetime.datetime) """
- if timestamp is None:
- return 'n/a'
- else:
- return datetime.datetime.strftime(timestamp, format)
-
- @app.template_filter('timefmt')
- def jinja_time_formatter(timestamp):
- """ Reformats a datetime timedelta """
- if timestamp is None:
- return 'n/a'
- else:
- date = datetime.timedelta(seconds=int(timestamp.total_seconds()))
- return str(date)
-
- @app.template_filter('to_nice_json')
- def jinja_to_nice_json(result):
- """ Tries to format a result as a pretty printed JSON. """
- try:
- return jsonutils.dumps(jsonutils.loads(result),
- indent=4,
- sort_keys=True)
- except (ValueError, TypeError):
- try:
- return jsonutils.dumps(result, indent=4, sort_keys=True)
- except TypeError as err:
- log.error('failed to dump json: %s', err)
- return result
-
- @app.template_filter('from_json')
- def jinja_from_json(val):
- try:
- return jsonutils.loads(val)
- except ValueError as err:
- log.error('failed to load json: %s', err)
- return val
-
- @app.template_filter('yamlhighlight')
- def jinja_yamlhighlight(code):
- formatter = HtmlFormatter(linenos='table',
- anchorlinenos=True,
- lineanchors='line',
- linespans='line',
- cssclass='codehilite')
-
- if not code:
- code = ''
-
- return highlight(Markup(code).unescape(),
- YamlLexer(stripall=True),
- formatter)
-
- @app.template_filter('pygments_formatter')
- def jinja_pygments_formatter(data):
- formatter = HtmlFormatter(cssclass='codehilite')
-
- if isinstance(data, dict) or isinstance(data, list):
- data = jsonutils.dumps(data, indent=4, sort_keys=True)
- lexer = JsonLexer()
- elif six.string_types or six.text_type:
- try:
- data = jsonutils.dumps(jsonutils.loads(data),
- indent=4,
- sort_keys=True)
- lexer = JsonLexer()
- except (ValueError, TypeError):
- lexer = TextLexer()
- else:
- lexer = TextLexer()
-
- lexer.stripall = True
- return highlight(Markup(data).unescape(), lexer, formatter)
-
- @app.template_filter('fast_count')
- def jinja_fast_count(query):
- return fast_count(query)
-
- @app.template_filter('basename')
- def jinja_basename(pathname):
- return path.basename(pathname)
-
- @app.template_filter('treeview')
- def jinja_treeview(playbook):
- return playbook_treeview(playbook)
diff --git a/ara/plugins/actions/ara_read.py b/ara/plugins/actions/ara_read.py
index 870991f0..d90ee348 100644
--- a/ara/plugins/actions/ara_read.py
+++ b/ara/plugins/actions/ara_read.py
@@ -15,10 +15,7 @@
# You should have received a copy of the GNU General Public License
# along with ARA. If not, see .
-import os
-
from ansible.plugins.action import ActionBase
-from oslo_serialization import jsonutils
try:
from ara import models
@@ -109,11 +106,6 @@ class ActionModule(ActionBase):
}
return result
- app = create_app()
- if not current_app:
- context = app.app_context()
- context.push()
-
for arg in self._task.args:
if arg not in self.VALID_ARGS:
result = {
@@ -134,12 +126,14 @@ class ActionModule(ActionBase):
result['msg'] = '{0} parameter is required'.format(parameter)
return result
+ app = create_app()
+ if not current_app:
+ context = app.app_context()
+ context.push()
+
if playbook_id is None:
- # Retrieve the persisted playbook_id from tmpfile
- tmpfile = os.path.join(app.config['ARA_TMP_DIR'], 'ara.json')
- with open(tmpfile, 'rb') as file:
- data = jsonutils.load(file)
- playbook_id = data['playbook']['id']
+ # Retrieve playbook_id from the cached context
+ playbook_id = current_app._cache['playbook']
try:
data = self.get_key(playbook_id, key)
diff --git a/ara/plugins/actions/ara_record.py b/ara/plugins/actions/ara_record.py
index 1c20e4c6..e95b94d5 100644
--- a/ara/plugins/actions/ara_record.py
+++ b/ara/plugins/actions/ara_record.py
@@ -15,10 +15,7 @@
# You should have received a copy of the GNU General Public License
# along with ARA. If not, see .
-import os
-
from ansible.plugins.action import ActionBase
-from oslo_serialization import jsonutils
try:
from ara import models
@@ -143,11 +140,6 @@ class ActionModule(ActionBase):
}
return result
- app = create_app()
- if not current_app:
- context = app.app_context()
- context.push()
-
for arg in self._task.args:
if arg not in self.VALID_ARGS:
result = {
@@ -178,12 +170,14 @@ class ActionModule(ActionBase):
result['msg'] = msg
return result
+ app = create_app()
+ if not current_app:
+ context = app.app_context()
+ context.push()
+
if playbook_id is None:
- # Retrieve the persisted playbook_id from tmpfile
- tmpfile = os.path.join(app.config['ARA_TMP_DIR'], 'ara.json')
- with open(tmpfile, 'rb') as file:
- data = jsonutils.load(file)
- playbook_id = data['playbook']['id']
+ # Retrieve playbook_id from the cached context
+ playbook_id = current_app._cache['playbook']
try:
self.create_or_update_key(playbook_id, key, value, type)
diff --git a/ara/plugins/callbacks/log_ara.py b/ara/plugins/callbacks/log_ara.py
index 95b9154d..bf3237b5 100644
--- a/ara/plugins/callbacks/log_ara.py
+++ b/ara/plugins/callbacks/log_ara.py
@@ -17,7 +17,6 @@
from __future__ import (absolute_import, division, print_function)
-import flask
import itertools
import logging
import os
@@ -29,6 +28,7 @@ from ara.models import db
from ara.webapp import create_app
from datetime import datetime
from distutils.version import LooseVersion
+from flask import current_app
from oslo_serialization import jsonutils
# To retrieve Ansible CLI options
@@ -62,7 +62,7 @@ class CallbackModule(CallbackBase):
def __init__(self):
super(CallbackModule, self).__init__()
- if not flask.current_app:
+ if not current_app:
ctx = app.app_context()
ctx.push()
@@ -333,15 +333,8 @@ class CallbackModule(CallbackBase):
file_ = self.get_or_create_file(path)
file_.is_playbook = True
- # We need to persist the playbook id so it can be used by the modules
- data = {
- 'playbook': {
- 'id': self.playbook.id
- }
- }
- tmpfile = os.path.join(app.config['ARA_TMP_DIR'], 'ara.json')
- with open(tmpfile, 'w') as file:
- file.write(jsonutils.dumps(data))
+ # Cache the playbook data in memory for ara_record/ara_read
+ current_app._cache['playbook'] = self.playbook.id
def v2_playbook_on_play_start(self, play):
self.close_task()
diff --git a/ara/plugins/modules/ara_read.py b/ara/plugins/modules/ara_read.py
deleted file mode 100644
index 7adf7150..00000000
--- a/ara/plugins/modules/ara_read.py
+++ /dev/null
@@ -1,74 +0,0 @@
-# Copyright (c) 2017 Red Hat, Inc.
-#
-# This file is part of ARA: Ansible Run Analysis.
-#
-# ARA is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# ARA is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with ARA. If not, see .
-
-# This file is purposefully left empty due to an Ansible issue
-# Details at: https://github.com/ansible/ansible/pull/18208
-
-# TODO: Remove this file and update the documentation when the issue is fixed,
-# released and present in all supported versions.
-
-DOCUMENTATION = """
----
-module: ara_read
-short_description: Ansible module to read recorded persistent data with ARA.
-version_added: "2.0"
-author: "RDO Community "
-description:
- - Ansible module to read recorded persistent data with ARA.
-options:
- playbook:
- description:
- - uuid of the playbook to read the key from
- required: false
- version_added: 0.13.2
- key:
- description:
- - Name of the key to read from
- required: true
-
-requirements:
- - "python >= 2.6"
- - "ara >= 0.10.0"
-"""
-
-EXAMPLES = """
-# Write data
-- ara_record:
- key: "foo"
- value: "bar"
-
-# Read data
-- ara_read:
- key: "foo"
- register: foo
-
-# Read data from a specific playbook
-# (Retrieve playbook uuid's with 'ara playbook list')
-- ara_read:
- playbook: uuuu-iiii-dddd-0000
- key: logs
- register: logs
-
-# Use data
-- debug:
- msg: "{{ item }}"
- with_items:
- - foo.key
- - foo.value
- - foo.type
- - foo.playbook_id
-"""
diff --git a/ara/plugins/modules/ara_record.py b/ara/plugins/modules/ara_record.py
deleted file mode 100644
index 20a30d9b..00000000
--- a/ara/plugins/modules/ara_record.py
+++ /dev/null
@@ -1,92 +0,0 @@
-# Copyright (c) 2017 Red Hat, Inc.
-#
-# This file is part of ARA: Ansible Run Analysis.
-#
-# ARA is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# ARA is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with ARA. If not, see .
-
-# This file is purposefully left empty due to an Ansible issue
-# Details at: https://github.com/ansible/ansible/pull/18208
-
-# TODO: Remove this file and update the documentation when the issue is fixed,
-# released and present in all supported versions.
-
-DOCUMENTATION = """
----
-module: ara_record
-short_description: Ansible module to record persistent data with ARA.
-version_added: "2.0"
-author: "RDO Community "
-description:
- - Ansible module to record persistent data with ARA.
-options:
- playbook:
- description:
- - uuid of the playbook to write the key to
- required: false
- version_added: 0.13.2
- key:
- description:
- - Name of the key to write data to
- required: true
- value:
- description:
- - Value of the key written to
- required: true
- type:
- description:
- - Type of the key
- choices: [text, url, json, list, dict]
- default: text
-
-requirements:
- - "python >= 2.6"
- - "ara >= 0.10.0"
-"""
-
-EXAMPLES = """
-# Write static data
-- ara_record:
- key: "foo"
- value: "bar"
-
-# Write data to a specific (previously run) playbook
-# (Retrieve playbook uuid's with 'ara playbook list')
-- ara_record:
- playbook: uuuu-iiii-dddd-0000
- key: logs
- value: "{{ lookup('file', '/var/log/ansible.log') }}"
- type: text
-
-# Write dynamic data
-- shell: cd dev && git rev-parse HEAD
- register: git_version
- delegate_to: localhost
-
-- ara_record:
- key: "git_version"
- value: "{{ git_version.stdout }}"
-
-# Write data with a type (otherwise defaults to "text")
-# This changes the behavior on how the value is presented in the web interface
-- ara_record:
- key: "{{ item.key }}"
- value: "{{ item.value }}"
- type: "{{ item.type }}"
- with_items:
- - { key: "log", value: "error", type: "text" }
- - { key: "website", value: "http://domain.tld", type: "url" }
- - { key: "data", value: "{ 'key': 'value' }", type: "json" }
- - { key: "somelist", value: ['one', 'two'], type: "list" }
- - { key: "somedict", value: {'key': 'value' }, type: "dict" }
-"""
diff --git a/ara/templates/about.html b/ara/templates/about.html
index d4c94bb3..f0666462 100644
--- a/ara/templates/about.html
+++ b/ara/templates/about.html
@@ -33,7 +33,7 @@
Tasks