Add support for Ansible 2.4

- Adjust configuration loading to work with 2.4
- Metaclass usage to automatically commit to the database no longer
  worked, worked around it by removing the metaclass altogether.
  The metaclass is no longer used in 1.0 so this is only a master
  branch change.

Change-Id: I0646b71a74d007f6f5cc9b4718fe2e222075e5e8
This commit is contained in:
David Moreau-Simard 2017-09-19 23:23:35 -04:00
parent 9ba142a2db
commit 3fc2068314
No known key found for this signature in database
GPG Key ID: 33A07694CBB71ECC
9 changed files with 152 additions and 24 deletions

View File

@ -25,8 +25,17 @@ import xstatic.pkg.patternfly_bootstrap_treeview
from ansible import __version__ as ansible_version
from ansible.constants import get_config
from ansible.constants import load_config_file
try:
from ansible.constants import load_config_file
except ImportError:
# Ansible 2.4 no longer provides load_config_file, this is handled further
# down
# Also, don't scream deprecated things at us
import ansible.constants
ansible.constants._deprecated = lambda *args: None
pass
from distutils.version import LooseVersion
from six.moves import configparser
def _ara_config(config, key, env_var, default=None, section='ara',
@ -82,7 +91,11 @@ DEFAULTS = {
}
# Bootstrap Ansible configuration
config, path = load_config_file()
# 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:
config = configparser.ConfigParser()
# Some defaults need to be based on top of a "processed" ARA_DIR
ARA_DIR = _ara_config(config, 'dir', 'ARA_DIR')

View File

@ -17,12 +17,10 @@
from __future__ import (absolute_import, division, print_function)
import decorator
import flask
import itertools
import logging
import os
import six
from ansible import __version__ as ansible_version
from ansible.plugins.callback import CallbackBase
@ -43,22 +41,6 @@ LOG = logging.getLogger('ara.callback')
app = create_app()
class CommitAfter(type):
def __new__(kls, name, bases, attrs):
def commit_after(func):
def _commit_after(func, *args, **kwargs):
rval = func(*args, **kwargs)
db.session.commit()
return rval
return decorator.decorate(func, _commit_after)
for k, v in attrs.items():
if callable(v) and not k.startswith('_'):
attrs[k] = commit_after(v)
return super(CommitAfter, kls).__new__(kls, name, bases, attrs)
class IncludeResult(object):
"""
This is used by the v2_playbook_on_include callback to synthesize a task
@ -69,7 +51,6 @@ class IncludeResult(object):
self._result = {'included_file': path}
@six.add_metaclass(CommitAfter)
class CallbackModule(CallbackBase):
"""
Saves data from an Ansible run into a database
@ -109,6 +90,7 @@ class CallbackModule(CallbackBase):
except models.NoResultFound:
host = models.Host(name=hostname, playbook=self.playbook)
db.session.add(host)
db.session.commit()
return host
@ -125,6 +107,7 @@ class CallbackModule(CallbackBase):
file_ = models.File(path=path, playbook=self.playbook)
db.session.add(file_)
db.session.commit()
try:
with open(path, 'r') as fd:
@ -190,6 +173,7 @@ class CallbackModule(CallbackBase):
)
db.session.add(self.taskresult)
db.session.commit()
if self.task.action == 'setup' and 'ansible_facts' in result._result:
values = jsonutils.dumps(result._result['ansible_facts'])
@ -197,6 +181,7 @@ class CallbackModule(CallbackBase):
host.facts = facts
db.session.add(facts)
db.session.commit()
def log_stats(self, stats):
"""
@ -216,6 +201,7 @@ class CallbackModule(CallbackBase):
ok=host_stats['ok'],
skipped=host_stats['skipped']
))
db.session.commit()
def close_task(self):
"""
@ -227,6 +213,7 @@ class CallbackModule(CallbackBase):
self.task.id)
self.task.stop()
db.session.add(self.task)
db.session.commit()
self.task = None
self.loop_items = []
@ -239,6 +226,7 @@ class CallbackModule(CallbackBase):
LOG.debug('closing play %s (%s)', self.play.name, self.play.id)
self.play.stop()
db.session.add(self.play)
db.session.commit()
self.play = None
@ -251,6 +239,7 @@ class CallbackModule(CallbackBase):
self.playbook.stop()
self.playbook.complete = True
db.session.add(self.playbook)
db.session.commit()
def v2_runner_item_on_ok(self, result):
self.loop_items.append(result)
@ -305,6 +294,7 @@ class CallbackModule(CallbackBase):
self.task.start()
db.session.add(self.task)
db.session.commit()
def v2_playbook_on_handler_task_start(self, task):
self.v2_playbook_on_task_start(task, False, is_handler=True)
@ -331,6 +321,7 @@ class CallbackModule(CallbackBase):
self.playbook.start()
db.session.add(self.playbook)
db.session.commit()
file_ = self.get_or_create_file(path)
file_.is_playbook = True
@ -361,6 +352,7 @@ class CallbackModule(CallbackBase):
self.play.start()
db.session.add(self.play)
db.session.commit()
def v2_playbook_on_stats(self, stats):
self.log_stats(stats)

View File

@ -0,0 +1,20 @@
---
# 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 <http://www.gnu.org/licenses/>.
- import_playbook: imported.yml

View File

@ -0,0 +1,34 @@
---
# 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 <http://www.gnu.org/licenses/>.
# Tests for the new import tasks from Ansible 2.4
- name: Import a role
hosts: localhost
gather_facts: no
tasks:
- name: Import role
import_role:
name: imported-role
- name: Include a role
hosts: localhost
gather_facts: no
tasks:
- name: Include role
include_role:
name: imported-role

View File

@ -0,0 +1,20 @@
---
# 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 <http://www.gnu.org/licenses/>.
role_message: "This message is from an imported role"
task_message: "This message is from an imported task in an imported role"

View File

@ -0,0 +1,20 @@
---
# 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 <http://www.gnu.org/licenses/>.
- debug:
msg: "{{ task_message }}"

View File

@ -0,0 +1,23 @@
---
# 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 <http://www.gnu.org/licenses/>.
- name: Import task
import_tasks: imported-task.yml
- name: Include task
include_tasks: imported-task.yml

View File

@ -1,7 +1,7 @@
pbr!=2.1.0,>=2.0.0 # Apache-2.0
jinja2>=2.9
ansible>=2.2.0.0,<2.4
ansible>=2.2.0.0
Flask>=0.11,<0.13
Flask-SQLAlchemy
Flask-Migrate

View File

@ -126,10 +126,10 @@ export ANSIBLE_LIBRARY="ara/plugins/modules"
export ARA_DATABASE="${DATABASE}"
# Lint
for file in $(find ara/tests/integration -regex '.*.y[a]?ml'); do
for file in $(find ara/tests/integration ! -path '*import*.yml' -regex '.*.y[a]?ml'); do
ansible-lint ${file}
done
for file in $(find ara/tests/integration -maxdepth 1 -regex '.*.y[a]?ml'); do
for file in $(find ara/tests/integration -maxdepth 1 ! -path '*import*.yml' -regex '.*.y[a]?ml'); do
ansible-playbook --syntax-check ${file}
done
@ -148,6 +148,12 @@ kill $!
# Test include role which is a bit special
ansible-playbook -vv ara/tests/integration/include_role.yml
if [[ $(semver_compare "${ansible_version}" ">=" "2.4.0.0") == "True" ]]; then
ansible-playbook --syntax-check ara/tests/integration/import.yml
ansible-lint ara/tests/integration/import.yml
ansible-playbook -vv ara/tests/integration/import.yml
fi
# Run test commands
pbid=$(ara playbook list -c ID -f value |head -n1)