mirror of https://github.com/ansible/ansible.git
Merge branch 'integration'
Conflicts: lib/ansible/playbook.py lib/ansible/runner.py library/aptpull/200/merge
commit
c00699d0ef
@ -1,5 +1,6 @@
|
||||
include README.md ansible.spec
|
||||
include README.md packaging/rpm/ansible.spec
|
||||
include examples/hosts
|
||||
include packaging/distutils/setup.py
|
||||
recursive-include docs *
|
||||
recursive-include library *
|
||||
include Makefile
|
||||
|
@ -1 +1,2 @@
|
||||
*.xml
|
||||
*.asciidoc
|
||||
|
@ -0,0 +1,18 @@
|
||||
---
|
||||
# This is a demo of how to manage the selinux context using the file module
|
||||
- hosts: test
|
||||
user: root
|
||||
tasks:
|
||||
- name: Change setype of /etc/exports to non-default value
|
||||
action: file path=/etc/exports setype=etc_t
|
||||
- name: Change seuser of /etc/exports to non-default value
|
||||
action: file path=/etc/exports seuser=unconfined_u
|
||||
- name: Set selinux context back to default value
|
||||
action: file path=/etc/exports context=default
|
||||
- name: Create empty file
|
||||
action: command /bin/touch /tmp/foo
|
||||
- name: Change setype of /tmp/foo
|
||||
action: file path=/tmp/foo setype=default_t
|
||||
- name: Try to set secontext to default, but this will fail
|
||||
because of the lack of a default in the policy
|
||||
action: file path=/tmp/foo context=default
|
@ -0,0 +1,292 @@
|
||||
# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
|
||||
#
|
||||
# This file is part of Ansible
|
||||
#
|
||||
# Ansible 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.
|
||||
#
|
||||
# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#############################################
|
||||
|
||||
import fnmatch
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
import constants as C
|
||||
from ansible import errors
|
||||
from ansible import utils
|
||||
|
||||
class Inventory(object):
|
||||
""" Host inventory for ansible.
|
||||
|
||||
The inventory is either a simple text file with systems and [groups] of
|
||||
systems, or a script that will be called with --list or --host.
|
||||
"""
|
||||
|
||||
def __init__(self, host_list=C.DEFAULT_HOST_LIST):
|
||||
|
||||
self._restriction = None
|
||||
self._variables = {}
|
||||
|
||||
if type(host_list) == list:
|
||||
self.host_list = host_list
|
||||
self.groups = dict(ungrouped=host_list)
|
||||
self._is_script = False
|
||||
return
|
||||
|
||||
inventory_file = os.path.expanduser(host_list)
|
||||
if not os.path.exists(inventory_file):
|
||||
raise errors.AnsibleFileNotFound("inventory file not found: %s" % host_list)
|
||||
|
||||
self.inventory_file = os.path.abspath(inventory_file)
|
||||
|
||||
if os.access(self.inventory_file, os.X_OK):
|
||||
self.host_list, self.groups = self._parse_from_script()
|
||||
self._is_script = True
|
||||
else:
|
||||
self.host_list, self.groups = self._parse_from_file()
|
||||
self._is_script = False
|
||||
|
||||
# *****************************************************
|
||||
# Public API
|
||||
|
||||
def list_hosts(self, pattern="all"):
|
||||
""" Return a list of hosts [matching the pattern] """
|
||||
if self._restriction is None:
|
||||
host_list = self.host_list
|
||||
else:
|
||||
host_list = [ h for h in self.host_list if h in self._restriction ]
|
||||
return [ h for h in host_list if self._matches(h, pattern) ]
|
||||
|
||||
def restrict_to(self, restriction):
|
||||
""" Restrict list operations to the hosts given in restriction """
|
||||
if type(restriction)!=list:
|
||||
restriction = [ restriction ]
|
||||
|
||||
self._restriction = restriction
|
||||
|
||||
def lift_restriction(self):
|
||||
""" Do not restrict list operations """
|
||||
self._restriction = None
|
||||
|
||||
def get_variables(self, host):
|
||||
""" Return the variables associated with this host. """
|
||||
|
||||
if host in self._variables:
|
||||
return self._variables[host].copy()
|
||||
|
||||
if not self._is_script:
|
||||
return {}
|
||||
|
||||
return self._get_variables_from_script(host)
|
||||
|
||||
# *****************************************************
|
||||
|
||||
def _parse_from_file(self):
|
||||
''' parse a textual host file '''
|
||||
|
||||
results = []
|
||||
groups = dict(ungrouped=[])
|
||||
lines = file(self.inventory_file).read().split("\n")
|
||||
if "---" in lines:
|
||||
return self._parse_yaml()
|
||||
group_name = 'ungrouped'
|
||||
for item in lines:
|
||||
item = item.lstrip().rstrip()
|
||||
if item.startswith("#"):
|
||||
# ignore commented out lines
|
||||
pass
|
||||
elif item.startswith("["):
|
||||
# looks like a group
|
||||
group_name = item.replace("[","").replace("]","").lstrip().rstrip()
|
||||
groups[group_name] = []
|
||||
elif item != "":
|
||||
# looks like a regular host
|
||||
if ":" in item:
|
||||
# a port was specified
|
||||
item, port = item.split(":")
|
||||
try:
|
||||
port = int(port)
|
||||
except ValueError:
|
||||
raise errors.AnsibleError("SSH port for %s in inventory (%s) should be numerical."%(item, port))
|
||||
self._set_variable(item, "ansible_ssh_port", port)
|
||||
groups[group_name].append(item)
|
||||
if not item in results:
|
||||
results.append(item)
|
||||
return (results, groups)
|
||||
|
||||
# *****************************************************
|
||||
|
||||
def _parse_from_script(self):
|
||||
''' evaluate a script that returns list of hosts by groups '''
|
||||
|
||||
results = []
|
||||
groups = dict(ungrouped=[])
|
||||
|
||||
cmd = [self.inventory_file, '--list']
|
||||
|
||||
cmd = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)
|
||||
out, err = cmd.communicate()
|
||||
rc = cmd.returncode
|
||||
if rc:
|
||||
raise errors.AnsibleError("%s: %s" % self.inventory_file, err)
|
||||
|
||||
try:
|
||||
groups = utils.json_loads(out)
|
||||
except:
|
||||
raise errors.AnsibleError("invalid JSON response from script: %s" % self.inventory_file)
|
||||
|
||||
for (groupname, hostlist) in groups.iteritems():
|
||||
for host in hostlist:
|
||||
if host not in results:
|
||||
results.append(host)
|
||||
return (results, groups)
|
||||
|
||||
# *****************************************************
|
||||
|
||||
def _parse_yaml(self):
|
||||
""" Load the inventory from a yaml file.
|
||||
|
||||
returns hosts and groups"""
|
||||
data = utils.parse_yaml_from_file(self.inventory_file)
|
||||
|
||||
if type(data) != list:
|
||||
raise errors.AnsibleError("YAML inventory should be a list.")
|
||||
|
||||
hosts = []
|
||||
groups = {}
|
||||
|
||||
ungrouped = []
|
||||
|
||||
for item in data:
|
||||
if type(item) == dict:
|
||||
if "group" in item:
|
||||
group_name = item["group"]
|
||||
|
||||
group_vars = []
|
||||
if "vars" in item:
|
||||
group_vars = item["vars"]
|
||||
|
||||
group_hosts = []
|
||||
if "hosts" in item:
|
||||
for host in item["hosts"]:
|
||||
host_name = self._parse_yaml_host(host, group_vars)
|
||||
group_hosts.append(host_name)
|
||||
|
||||
groups[group_name] = group_hosts
|
||||
hosts.extend(group_hosts)
|
||||
|
||||
elif "host" in item:
|
||||
host_name = self._parse_yaml_host(item)
|
||||
hosts.append(host_name)
|
||||
ungrouped.append(host_name)
|
||||
else:
|
||||
host_name = self._parse_yaml_host(item)
|
||||
hosts.append(host_name)
|
||||
ungrouped.append(host_name)
|
||||
|
||||
# filter duplicate hosts
|
||||
output_hosts = []
|
||||
for host in hosts:
|
||||
if host not in output_hosts:
|
||||
output_hosts.append(host)
|
||||
|
||||
if len(ungrouped) > 0 :
|
||||
# hosts can be defined top-level, but also in a group
|
||||
really_ungrouped = []
|
||||
for host in ungrouped:
|
||||
already_grouped = False
|
||||
for name, group_hosts in groups.items():
|
||||
if host in group_hosts:
|
||||
already_grouped = True
|
||||
if not already_grouped:
|
||||
really_ungrouped.append(host)
|
||||
groups["ungrouped"] = really_ungrouped
|
||||
|
||||
return output_hosts, groups
|
||||
|
||||
def _parse_yaml_host(self, item, variables=[]):
|
||||
def set_variables(host, variables):
|
||||
if type(variables) == list:
|
||||
for variable in variables:
|
||||
if len(variable) != 1:
|
||||
raise errors.AnsibleError("Only one item expected in %s"%(variable))
|
||||
k, v = variable.items()[0]
|
||||
self._set_variable(host, k, v)
|
||||
elif type(variables) == dict:
|
||||
for k, v in variables.iteritems():
|
||||
self._set_variable(host, k, v)
|
||||
|
||||
|
||||
if type(item) in [str, unicode]:
|
||||
set_variables(item, variables)
|
||||
return item
|
||||
elif type(item) == dict:
|
||||
if "host" in item:
|
||||
host_name = item["host"]
|
||||
set_variables(host_name, variables)
|
||||
|
||||
if "vars" in item:
|
||||
set_variables(host_name, item["vars"])
|
||||
|
||||
return host_name
|
||||
else:
|
||||
raise errors.AnsibleError("Unknown item in inventory: %s"%(item))
|
||||
|
||||
|
||||
def _get_variables_from_script(self, host):
|
||||
''' support per system variabes from external variable scripts, see web docs '''
|
||||
|
||||
cmd = [self.inventory_file, '--host', host]
|
||||
|
||||
cmd = subprocess.Popen(cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
shell=False
|
||||
)
|
||||
out, err = cmd.communicate()
|
||||
|
||||
variables = {}
|
||||
try:
|
||||
variables = utils.json_loads(out)
|
||||
except:
|
||||
raise errors.AnsibleError("%s returned invalid result when called with hostname %s" % (
|
||||
self.inventory_file,
|
||||
host
|
||||
))
|
||||
return variables
|
||||
|
||||
def _set_variable(self, host, key, value):
|
||||
if not host in self._variables:
|
||||
self._variables[host] = {}
|
||||
self._variables[host][key] = value
|
||||
|
||||
def _matches(self, host_name, pattern):
|
||||
''' returns if a hostname is matched by the pattern '''
|
||||
|
||||
# a pattern is in fnmatch format but more than one pattern
|
||||
# can be strung together with semicolons. ex:
|
||||
# atlanta-web*.example.com;dc-web*.example.com
|
||||
|
||||
if host_name == '':
|
||||
return False
|
||||
pattern = pattern.replace(";",":")
|
||||
subpatterns = pattern.split(":")
|
||||
for subpattern in subpatterns:
|
||||
if subpattern == 'all':
|
||||
return True
|
||||
if fnmatch.fnmatch(host_name, subpattern):
|
||||
return True
|
||||
elif subpattern in self.groups:
|
||||
if host_name in self.groups[subpattern]:
|
||||
return True
|
||||
return False
|
@ -0,0 +1,71 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
|
||||
#
|
||||
# This file is part of Ansible
|
||||
#
|
||||
# Ansible 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.
|
||||
#
|
||||
# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import sys
|
||||
import os
|
||||
import shlex
|
||||
import base64
|
||||
|
||||
try:
|
||||
import json
|
||||
except ImportError:
|
||||
import simplejson as json
|
||||
|
||||
# ===========================================
|
||||
# convert arguments of form a=b c=d
|
||||
# to a dictionary
|
||||
|
||||
if len(sys.argv) == 1:
|
||||
sys.exit(1)
|
||||
argfile = sys.argv[1]
|
||||
if not os.path.exists(argfile):
|
||||
sys.exit(1)
|
||||
items = shlex.split(open(argfile, 'r').read())
|
||||
|
||||
params = {}
|
||||
for x in items:
|
||||
(k, v) = x.split("=")
|
||||
params[k] = v
|
||||
source = os.path.expanduser(params['src'])
|
||||
|
||||
# ==========================================
|
||||
|
||||
# raise an error if there is no template metadata
|
||||
if not os.path.exists(source):
|
||||
print json.dumps(dict(
|
||||
failed = 1,
|
||||
msg = "file not found: %s" % source
|
||||
))
|
||||
sys.exit(1)
|
||||
|
||||
if not os.access(source, os.R_OK):
|
||||
print json.dumps(dict(
|
||||
failed = 1,
|
||||
msg = "file is not readable: %s" % source
|
||||
))
|
||||
sys.exit(1)
|
||||
|
||||
# ==========================================
|
||||
|
||||
data = file(source).read()
|
||||
data = base64.b64encode(data)
|
||||
|
||||
print json.dumps(dict(content=data, encoding='base64'))
|
||||
sys.exit(0)
|
||||
|
@ -0,0 +1,44 @@
|
||||
#Maintainer: Michel Blanc <mblanc@erasme.org>
|
||||
pkgname=ansible-git
|
||||
pkgver=20120419
|
||||
pkgrel=1
|
||||
pkgdesc="A radically simple deployment, model-driven configuration management, and command execution framework"
|
||||
arch=('any')
|
||||
url="https://github.com/ansible/ansible"
|
||||
license=('GPL3')
|
||||
depends=('python2' 'python2-yaml' 'python-paramiko>=1.7.7' 'python2-jinja' 'python-simplejson')
|
||||
makedepends=('git' 'asciidoc' 'fakeroot')
|
||||
|
||||
_gitroot="https://github.com/ansible/ansible"
|
||||
_gitname="ansible"
|
||||
|
||||
build() {
|
||||
cd "$srcdir"
|
||||
msg "Connecting to GIT server...."
|
||||
|
||||
if [ -d $_gitname ] ; then
|
||||
cd $_gitname && git pull origin
|
||||
msg "The local files are updated."
|
||||
else
|
||||
git clone $_gitroot $_gitname
|
||||
fi
|
||||
|
||||
msg "GIT checkout done or server timeout"
|
||||
|
||||
cd "$srcdir/$_gitname"
|
||||
make
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$srcdir/$_gitname"
|
||||
|
||||
mkdir -p ${pkgdir}/usr/share/ansible
|
||||
cp ./library/* ${pkgdir}/usr/share/ansible/
|
||||
python setup.py install -O1 --root=${pkgdir}
|
||||
|
||||
install -D docs/man/man1/ansible.1 ${pkgdir}/usr/share/man/man1/ansible.1
|
||||
install -D docs/man/man1/ansible-playbook.1 ${pkgdir}/usr/share/man/man1/ansible-playbook.1
|
||||
|
||||
gzip -9 ${pkgdir}/usr/share/man/man1/ansible.1
|
||||
gzip -9 ${pkgdir}/usr/share/man/man1/ansible-playbook.1
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
I have added a debian folder for use in building a .deb file for ansible. From the ansible directory you can run the following command to construct a debian package of ansible.
|
||||
|
||||
~/ansible$ dpkg-buildpackage -us -uc -rfakeroot
|
||||
|
||||
The debian package files will be placed in the ../ directory and can be installed with the following command:
|
||||
~/$ sudo dpkg -i .deb
|
||||
|
||||
Dpkg -i doesn't resolve dependencies, so if the previous command fails because of dependencies, you will need to run the following to install the dependencies (if needed) and then re-run the dpkg -i command to install the package:
|
||||
$ sudo apt-get -f install
|
||||
|
||||
--Henry Graham
|
@ -0,0 +1,3 @@
|
||||
etc/ansible
|
||||
usr/lib/python2.7/site-packages
|
||||
usr/share/ansible
|
@ -0,0 +1,5 @@
|
||||
examples/hosts etc/ansible
|
||||
library/* usr/share/ansible
|
||||
docs/man/man1/ansible.1 usr/share/man/man1
|
||||
docs/man/man1/ansible-playbook.1 usr/share/man/man1
|
||||
bin/* usr/bin
|
@ -0,0 +1,5 @@
|
||||
ansible (0.0.2) debian; urgency=low
|
||||
|
||||
* Initial Release
|
||||
|
||||
-- Henry Graham (hzgraham) <Henry.Graham@mail.wvu.edu> Tue, 17 Apr 2012 17:17:01 -0400
|
@ -0,0 +1 @@
|
||||
5
|
@ -0,0 +1,13 @@
|
||||
Source: ansible
|
||||
Section: admin
|
||||
Priority: optional
|
||||
Maintainer: Henry Graham (hzgraham) <Henry.Graham@mail.wvu.edu>
|
||||
Build-Depends: cdbs, debhelper (>= 5.0.0)
|
||||
Standards-Version: 3.9.1
|
||||
Homepage: http://ansible.github.com/
|
||||
|
||||
Package: ansible
|
||||
Architecture: all
|
||||
Depends: python, python-support (>= 0.90), python-jinja2, python-yaml, python-paramiko
|
||||
Description: Ansible Application
|
||||
Ansible is a extra-simple tool/API for doing 'parallel remote things' over SSH executing commands, running "modules", or executing larger 'playbooks' that can serve as a configuration management or deployment system.
|
@ -0,0 +1,26 @@
|
||||
This package was debianized by Henry Graham (hzgraham) <Henry.Graham@mail.wvu.edu> on
|
||||
Tue, 17 Apr 2012 12:19:47 -0400.
|
||||
|
||||
It was downloaded from https://github.com/ansible/ansible.git
|
||||
|
||||
Copyright: Henry Graham (hzgraham) <Henry.Graham@mail.wvu.edu>
|
||||
|
||||
License:
|
||||
|
||||
This package 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; version 2 dated June, 1991.
|
||||
|
||||
This package 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 this package; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
|
||||
USA.
|
||||
|
||||
On Debian systems, the complete text of the GNU General
|
||||
Public License can be found in `/usr/share/common-licenses/GPL'.
|
||||
|
@ -0,0 +1 @@
|
||||
README.md
|
@ -0,0 +1 @@
|
||||
2
|
@ -0,0 +1,6 @@
|
||||
#!/usr/bin/make -f
|
||||
# -- makefile --
|
||||
|
||||
include /usr/share/cdbs/1/rules/debhelper.mk
|
||||
DEB_PYTHON_SYSTEM = pysupport
|
||||
include /usr/share/cdbs/1/class/python-distutils.mk
|
@ -0,0 +1,3 @@
|
||||
Gentoo ebuilds are available here:
|
||||
|
||||
https://github.com/uu/ubuilds
|
@ -0,0 +1,252 @@
|
||||
import os
|
||||
import unittest
|
||||
|
||||
from ansible.inventory import Inventory
|
||||
from ansible.runner import Runner
|
||||
|
||||
class TestInventory(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.cwd = os.getcwd()
|
||||
self.test_dir = os.path.join(self.cwd, 'test')
|
||||
|
||||
self.inventory_file = os.path.join(self.test_dir, 'simple_hosts')
|
||||
self.inventory_script = os.path.join(self.test_dir, 'inventory_api.py')
|
||||
self.inventory_yaml = os.path.join(self.test_dir, 'yaml_hosts')
|
||||
|
||||
os.chmod(self.inventory_script, 0755)
|
||||
|
||||
def tearDown(self):
|
||||
os.chmod(self.inventory_script, 0644)
|
||||
|
||||
### Simple inventory format tests
|
||||
|
||||
def simple_inventory(self):
|
||||
return Inventory( self.inventory_file )
|
||||
|
||||
def script_inventory(self):
|
||||
return Inventory( self.inventory_script )
|
||||
|
||||
def yaml_inventory(self):
|
||||
return Inventory( self.inventory_yaml )
|
||||
|
||||
def test_simple(self):
|
||||
inventory = self.simple_inventory()
|
||||
hosts = inventory.list_hosts()
|
||||
|
||||
expected_hosts=['jupiter', 'saturn', 'zeus', 'hera', 'poseidon', 'thor', 'odin', 'loki']
|
||||
assert hosts == expected_hosts
|
||||
|
||||
def test_simple_all(self):
|
||||
inventory = self.simple_inventory()
|
||||
hosts = inventory.list_hosts('all')
|
||||
|
||||
expected_hosts=['jupiter', 'saturn', 'zeus', 'hera', 'poseidon', 'thor', 'odin', 'loki']
|
||||
assert hosts == expected_hosts
|
||||
|
||||
def test_simple_norse(self):
|
||||
inventory = self.simple_inventory()
|
||||
hosts = inventory.list_hosts("norse")
|
||||
|
||||
expected_hosts=['thor', 'odin', 'loki']
|
||||
assert hosts == expected_hosts
|
||||
|
||||
def test_simple_ungrouped(self):
|
||||
inventory = self.simple_inventory()
|
||||
hosts = inventory.list_hosts("ungrouped")
|
||||
|
||||
expected_hosts=['jupiter', 'saturn']
|
||||
assert hosts == expected_hosts
|
||||
|
||||
def test_simple_combined(self):
|
||||
inventory = self.simple_inventory()
|
||||
hosts = inventory.list_hosts("norse:greek")
|
||||
|
||||
expected_hosts=['zeus', 'hera', 'poseidon', 'thor', 'odin', 'loki']
|
||||
assert hosts == expected_hosts
|
||||
|
||||
def test_simple_restrict(self):
|
||||
inventory = self.simple_inventory()
|
||||
|
||||
restricted_hosts = ['hera', 'poseidon', 'thor']
|
||||
expected_hosts=['zeus', 'hera', 'poseidon', 'thor', 'odin', 'loki']
|
||||
|
||||
inventory.restrict_to(restricted_hosts)
|
||||
hosts = inventory.list_hosts("norse:greek")
|
||||
|
||||
assert hosts == restricted_hosts
|
||||
|
||||
inventory.lift_restriction()
|
||||
hosts = inventory.list_hosts("norse:greek")
|
||||
|
||||
assert hosts == expected_hosts
|
||||
|
||||
def test_simple_vars(self):
|
||||
inventory = self.simple_inventory()
|
||||
vars = inventory.get_variables('thor')
|
||||
|
||||
assert vars == {}
|
||||
|
||||
def test_simple_port(self):
|
||||
inventory = self.simple_inventory()
|
||||
vars = inventory.get_variables('hera')
|
||||
|
||||
assert vars == {'ansible_ssh_port': 3000}
|
||||
|
||||
### Inventory API tests
|
||||
|
||||
def test_script(self):
|
||||
inventory = self.script_inventory()
|
||||
hosts = inventory.list_hosts()
|
||||
|
||||
expected_hosts=['jupiter', 'saturn', 'zeus', 'hera', 'poseidon', 'thor', 'odin', 'loki']
|
||||
|
||||
print "Expected: %s"%(expected_hosts)
|
||||
print "Got : %s"%(hosts)
|
||||
assert sorted(hosts) == sorted(expected_hosts)
|
||||
|
||||
def test_script_all(self):
|
||||
inventory = self.script_inventory()
|
||||
hosts = inventory.list_hosts('all')
|
||||
|
||||
expected_hosts=['jupiter', 'saturn', 'zeus', 'hera', 'poseidon', 'thor', 'odin', 'loki']
|
||||
assert sorted(hosts) == sorted(expected_hosts)
|
||||
|
||||
def test_script_norse(self):
|
||||
inventory = self.script_inventory()
|
||||
hosts = inventory.list_hosts("norse")
|
||||
|
||||
expected_hosts=['thor', 'odin', 'loki']
|
||||
assert sorted(hosts) == sorted(expected_hosts)
|
||||
|
||||
def test_script_combined(self):
|
||||
inventory = self.script_inventory()
|
||||
hosts = inventory.list_hosts("norse:greek")
|
||||
|
||||
expected_hosts=['zeus', 'hera', 'poseidon', 'thor', 'odin', 'loki']
|
||||
assert sorted(hosts) == sorted(expected_hosts)
|
||||
|
||||
def test_script_restrict(self):
|
||||
inventory = self.script_inventory()
|
||||
|
||||
restricted_hosts = ['hera', 'poseidon', 'thor']
|
||||
expected_hosts=['zeus', 'hera', 'poseidon', 'thor', 'odin', 'loki']
|
||||
|
||||
inventory.restrict_to(restricted_hosts)
|
||||
hosts = inventory.list_hosts("norse:greek")
|
||||
|
||||
assert sorted(hosts) == sorted(restricted_hosts)
|
||||
|
||||
inventory.lift_restriction()
|
||||
hosts = inventory.list_hosts("norse:greek")
|
||||
|
||||
assert sorted(hosts) == sorted(expected_hosts)
|
||||
|
||||
def test_script_vars(self):
|
||||
inventory = self.script_inventory()
|
||||
vars = inventory.get_variables('thor')
|
||||
|
||||
assert vars == {"hammer":True}
|
||||
|
||||
### Tests for yaml inventory file
|
||||
|
||||
def test_yaml(self):
|
||||
inventory = self.yaml_inventory()
|
||||
hosts = inventory.list_hosts()
|
||||
print hosts
|
||||
expected_hosts=['jupiter', 'saturn', 'zeus', 'hera', 'poseidon', 'thor', 'odin', 'loki']
|
||||
assert hosts == expected_hosts
|
||||
|
||||
def test_yaml_all(self):
|
||||
inventory = self.yaml_inventory()
|
||||
hosts = inventory.list_hosts('all')
|
||||
|
||||
expected_hosts=['jupiter', 'saturn', 'zeus', 'hera', 'poseidon', 'thor', 'odin', 'loki']
|
||||
assert hosts == expected_hosts
|
||||
|
||||
def test_yaml_norse(self):
|
||||
inventory = self.yaml_inventory()
|
||||
hosts = inventory.list_hosts("norse")
|
||||
|
||||
expected_hosts=['thor', 'odin', 'loki']
|
||||
assert hosts == expected_hosts
|
||||
|
||||
def test_simple_ungrouped(self):
|
||||
inventory = self.yaml_inventory()
|
||||
hosts = inventory.list_hosts("ungrouped")
|
||||
|
||||
expected_hosts=['jupiter']
|
||||
assert hosts == expected_hosts
|
||||
|
||||
def test_yaml_combined(self):
|
||||
inventory = self.yaml_inventory()
|
||||
hosts = inventory.list_hosts("norse:greek")
|
||||
|
||||
expected_hosts=['zeus', 'hera', 'poseidon', 'thor', 'odin', 'loki']
|
||||
assert hosts == expected_hosts
|
||||
|
||||
def test_yaml_restrict(self):
|
||||
inventory = self.yaml_inventory()
|
||||
|
||||
restricted_hosts = ['hera', 'poseidon', 'thor']
|
||||
expected_hosts=['zeus', 'hera', 'poseidon', 'thor', 'odin', 'loki']
|
||||
|
||||
inventory.restrict_to(restricted_hosts)
|
||||
hosts = inventory.list_hosts("norse:greek")
|
||||
|
||||
assert hosts == restricted_hosts
|
||||
|
||||
inventory.lift_restriction()
|
||||
hosts = inventory.list_hosts("norse:greek")
|
||||
|
||||
assert hosts == expected_hosts
|
||||
|
||||
def test_yaml_vars(self):
|
||||
inventory = self.yaml_inventory()
|
||||
vars = inventory.get_variables('thor')
|
||||
|
||||
assert vars == {"hammer":True}
|
||||
|
||||
def test_yaml_change_vars(self):
|
||||
inventory = self.yaml_inventory()
|
||||
vars = inventory.get_variables('thor')
|
||||
|
||||
vars["hammer"] = False
|
||||
|
||||
vars = inventory.get_variables('thor')
|
||||
assert vars == {"hammer":True}
|
||||
|
||||
def test_yaml_host_vars(self):
|
||||
inventory = self.yaml_inventory()
|
||||
vars = inventory.get_variables('saturn')
|
||||
|
||||
assert vars == {"moon":"titan", "moon2":"enceladus"}
|
||||
|
||||
def test_yaml_port(self):
|
||||
inventory = self.yaml_inventory()
|
||||
vars = inventory.get_variables('hera')
|
||||
|
||||
assert vars == {'ansible_ssh_port': 3000, 'ntp_server': 'olympus.example.com'}
|
||||
|
||||
### Test Runner class method
|
||||
|
||||
def test_class_method(self):
|
||||
hosts, groups = Runner.parse_hosts(self.inventory_file)
|
||||
|
||||
expected_hosts = ['jupiter', 'saturn', 'zeus', 'hera', 'poseidon', 'thor', 'odin', 'loki']
|
||||
assert hosts == expected_hosts
|
||||
|
||||
expected_groups= {
|
||||
'ungrouped': ['jupiter', 'saturn'],
|
||||
'greek': ['zeus', 'hera', 'poseidon'],
|
||||
'norse': ['thor', 'odin', 'loki']
|
||||
}
|
||||
assert groups == expected_groups
|
||||
|
||||
def test_class_override(self):
|
||||
override_hosts = ['thor', 'odin']
|
||||
hosts, groups = Runner.parse_hosts(self.inventory_file, override_hosts)
|
||||
|
||||
assert hosts == override_hosts
|
||||
|
||||
assert groups == { 'ungrouped': override_hosts }
|
@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import json
|
||||
import sys
|
||||
|
||||
from optparse import OptionParser
|
||||
|
||||
parser = OptionParser()
|
||||
parser.add_option('-l', '--list', default=False, dest="list_hosts", action="store_true")
|
||||
parser.add_option('-H', '--host', default=None, dest="host")
|
||||
parser.add_option('-e', '--extra-vars', default=None, dest="extra")
|
||||
|
||||
options, args = parser.parse_args()
|
||||
|
||||
systems = {
|
||||
"ungouped": [ "jupiter", "saturn" ],
|
||||
"greek": [ "zeus", "hera", "poseidon" ],
|
||||
"norse": [ "thor", "odin", "loki" ]
|
||||
}
|
||||
|
||||
variables = {
|
||||
"thor": {
|
||||
"hammer": True
|
||||
}
|
||||
}
|
||||
|
||||
if options.list_hosts == True:
|
||||
print json.dumps(systems)
|
||||
sys.exit(0)
|
||||
|
||||
if options.host is not None:
|
||||
if options.extra:
|
||||
k,v = options.extra.split("=")
|
||||
variables[options.host][k] = v
|
||||
print json.dumps(variables[options.host])
|
||||
sys.exit(0)
|
||||
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
@ -0,0 +1,12 @@
|
||||
jupiter
|
||||
saturn
|
||||
|
||||
[greek]
|
||||
zeus
|
||||
hera:3000
|
||||
poseidon
|
||||
|
||||
[norse]
|
||||
thor
|
||||
odin
|
||||
loki
|
@ -0,0 +1,30 @@
|
||||
---
|
||||
|
||||
- jupiter
|
||||
- host: saturn
|
||||
vars:
|
||||
moon: titan
|
||||
moon2: enceladus
|
||||
|
||||
- zeus
|
||||
|
||||
- group: greek
|
||||
hosts:
|
||||
- zeus
|
||||
- hera
|
||||
- poseidon
|
||||
vars:
|
||||
- ansible_ssh_port: 3000
|
||||
- ntp_server: olympus.example.com
|
||||
|
||||
- group: norse
|
||||
hosts:
|
||||
- host: thor
|
||||
vars:
|
||||
- hammer: True
|
||||
- odin
|
||||
- loki
|
||||
|
||||
- group: multiple
|
||||
hosts:
|
||||
- saturn
|
Loading…
Reference in New Issue