Script to migrate YAML users to the INI format, so we can deprecate YAML inventory (which we are now doing).
This commit is contained in:
parent
b15dde6b9f
commit
5a67a556cd
4 changed files with 213 additions and 2 deletions
206
examples/scripts/yaml_to_ini.py
Normal file
206
examples/scripts/yaml_to_ini.py
Normal file
|
@ -0,0 +1,206 @@
|
|||
# (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 ansible.constants as C
|
||||
from ansible.inventory.host import Host
|
||||
from ansible.inventory.group import Group
|
||||
from ansible import errors
|
||||
from ansible import utils
|
||||
import os
|
||||
import yaml
|
||||
import sys
|
||||
|
||||
class InventoryParserYaml(object):
|
||||
''' Host inventory parser for ansible '''
|
||||
|
||||
def __init__(self, filename=C.DEFAULT_HOST_LIST):
|
||||
|
||||
sys.stderr.write("WARNING: YAML inventory files are deprecated in 0.6 and will be removed in 0.7, to migrate" +
|
||||
" download and run https://github.com/ansible/ansible/blob/devel/examples/scripts/yaml_to_ini.py\n")
|
||||
|
||||
fh = open(filename)
|
||||
data = fh.read()
|
||||
fh.close()
|
||||
self._hosts = {}
|
||||
self._parse(data)
|
||||
|
||||
def _make_host(self, hostname):
|
||||
|
||||
if hostname in self._hosts:
|
||||
return self._hosts[hostname]
|
||||
else:
|
||||
host = Host(hostname)
|
||||
self._hosts[hostname] = host
|
||||
return host
|
||||
|
||||
# see file 'test/yaml_hosts' for syntax
|
||||
|
||||
def _parse(self, data):
|
||||
# FIXME: refactor into subfunctions
|
||||
|
||||
all = Group('all')
|
||||
|
||||
ungrouped = Group('ungrouped')
|
||||
all.add_child_group(ungrouped)
|
||||
|
||||
self.groups = dict(all=all, ungrouped=ungrouped)
|
||||
grouped_hosts = []
|
||||
|
||||
yaml = utils.parse_yaml(data)
|
||||
|
||||
# first add all groups
|
||||
for item in yaml:
|
||||
if type(item) == dict and 'group' in item:
|
||||
group = Group(item['group'])
|
||||
|
||||
for subresult in item.get('hosts',[]):
|
||||
|
||||
if type(subresult) in [ str, unicode ]:
|
||||
host = self._make_host(subresult)
|
||||
group.add_host(host)
|
||||
grouped_hosts.append(host)
|
||||
elif type(subresult) == dict:
|
||||
host = self._make_host(subresult['host'])
|
||||
vars = subresult.get('vars',{})
|
||||
if type(vars) == list:
|
||||
for subitem in vars:
|
||||
for (k,v) in subitem.items():
|
||||
host.set_variable(k,v)
|
||||
elif type(vars) == dict:
|
||||
for (k,v) in subresult.get('vars',{}).items():
|
||||
host.set_variable(k,v)
|
||||
else:
|
||||
raise errors.AnsibleError("unexpected type for variable")
|
||||
group.add_host(host)
|
||||
grouped_hosts.append(host)
|
||||
|
||||
vars = item.get('vars',{})
|
||||
if type(vars) == dict:
|
||||
for (k,v) in item.get('vars',{}).items():
|
||||
group.set_variable(k,v)
|
||||
elif type(vars) == list:
|
||||
for subitem in vars:
|
||||
if type(subitem) != dict:
|
||||
raise errors.AnsibleError("expected a dictionary")
|
||||
for (k,v) in subitem.items():
|
||||
group.set_variable(k,v)
|
||||
|
||||
self.groups[group.name] = group
|
||||
all.add_child_group(group)
|
||||
|
||||
# add host definitions
|
||||
for item in yaml:
|
||||
if type(item) in [ str, unicode ]:
|
||||
host = self._make_host(item)
|
||||
if host not in grouped_hosts:
|
||||
ungrouped.add_host(host)
|
||||
|
||||
elif type(item) == dict and 'host' in item:
|
||||
host = self._make_host(item['host'])
|
||||
|
||||
vars = item.get('vars', {})
|
||||
if type(vars)==list:
|
||||
varlist, vars = vars, {}
|
||||
for subitem in varlist:
|
||||
vars.update(subitem)
|
||||
for (k,v) in vars.items():
|
||||
host.set_variable(k,v)
|
||||
|
||||
groups = item.get('groups', {})
|
||||
if type(groups) in [ str, unicode ]:
|
||||
groups = [ groups ]
|
||||
if type(groups)==list:
|
||||
for subitem in groups:
|
||||
if subitem in self.groups:
|
||||
group = self.groups[subitem]
|
||||
else:
|
||||
group = Group(subitem)
|
||||
self.groups[group.name] = group
|
||||
all.add_child_group(group)
|
||||
group.add_host(host)
|
||||
grouped_hosts.append(host)
|
||||
|
||||
if host not in grouped_hosts:
|
||||
ungrouped.add_host(host)
|
||||
|
||||
# make sure ungrouped.hosts is the complement of grouped_hosts
|
||||
ungrouped_hosts = [host for host in ungrouped.hosts if host not in grouped_hosts]
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 2:
|
||||
print "usage: yaml_to_ini.py /path/to/ansible/hosts"
|
||||
sys.exit(1)
|
||||
|
||||
result = ""
|
||||
|
||||
original = sys.argv[1]
|
||||
yamlp = InventoryParserYaml(filename=sys.argv[1])
|
||||
dirname = os.path.dirname(original)
|
||||
|
||||
group_names = [ g.name for g in yamlp.groups.values() ]
|
||||
|
||||
for group_name in sorted(group_names):
|
||||
|
||||
record = yamlp.groups[group_name]
|
||||
|
||||
if group_name == 'all':
|
||||
continue
|
||||
|
||||
hosts = record.hosts
|
||||
result = result + "[%s]\n" % record.name
|
||||
for h in hosts:
|
||||
result = result + "%s\n" % h.name
|
||||
result = result + "\n"
|
||||
|
||||
groupfiledir = os.path.join(dirname, "group_vars")
|
||||
if not os.path.exists(groupfiledir):
|
||||
print "* creating: %s" % groupfiledir
|
||||
os.makedirs(groupfiledir)
|
||||
groupfile = os.path.join(groupfiledir, group_name)
|
||||
print "* writing group variables for %s into %s" % (group_name, groupfile)
|
||||
groupfh = open(groupfile, 'w')
|
||||
groupfh.write(yaml.dump(record.get_variables()))
|
||||
groupfh.close()
|
||||
|
||||
for (host_name, host_record) in yamlp._hosts.iteritems():
|
||||
hostfiledir = os.path.join(dirname, "host_vars")
|
||||
if not os.path.exists(hostfiledir):
|
||||
print "* creating: %s" % hostfiledir
|
||||
os.makedirs(hostfiledir)
|
||||
hostfile = os.path.join(hostfiledir, host_record.name)
|
||||
print "* writing host variables for %s into %s" % (host_record.name, hostfile)
|
||||
hostfh = open(hostfile, 'w')
|
||||
hostfh.write(yaml.dump(host_record.get_variables()))
|
||||
hostfh.close()
|
||||
|
||||
|
||||
# also need to keep a hash of variables per each host
|
||||
# and variables per each group
|
||||
# and write those to disk
|
||||
|
||||
newfilepath = os.path.join(dirname, "hosts.new")
|
||||
fdh = open(newfilepath, 'w')
|
||||
fdh.write(result)
|
||||
fdh.close()
|
||||
|
||||
print "* COMPLETE: review your new inventory file and replace your original when ready"
|
||||
print "* new inventory file saved as %s" % newfilepath
|
||||
print "* edit group specific variables in %s/group_vars/" % dirname
|
||||
print "* edit host specific variables in %s/host_vars/" % dirname
|
||||
|
||||
# now need to write this to disk as (oldname).new
|
||||
# and inform the user
|
|
@ -47,6 +47,7 @@ class InventoryParser(object):
|
|||
self._parse_group_variables()
|
||||
return self.groups
|
||||
|
||||
|
||||
# [webservers]
|
||||
# alpha
|
||||
# beta:2345
|
||||
|
|
|
@ -20,12 +20,16 @@ from ansible.inventory.host import Host
|
|||
from ansible.inventory.group import Group
|
||||
from ansible import errors
|
||||
from ansible import utils
|
||||
import sys
|
||||
|
||||
class InventoryParserYaml(object):
|
||||
''' Host inventory parser for ansible '''
|
||||
|
||||
def __init__(self, filename=C.DEFAULT_HOST_LIST):
|
||||
|
||||
sys.stderr.write("WARNING: YAML inventory files are deprecated in 0.6 and will be removed in 0.7, to migrate" +
|
||||
" download and run https://github.com/ansible/ansible/blob/devel/examples/scripts/yaml_to_ini.py\n")
|
||||
|
||||
fh = open(filename)
|
||||
data = fh.read()
|
||||
fh.close()
|
||||
|
|
|
@ -508,8 +508,8 @@ class Runner(object):
|
|||
if type(exec_rc) != ReturnData:
|
||||
raise Exception("unexpected return type: %s" % type(exec_rc))
|
||||
# redundant, right?
|
||||
#if not exec_rc.comm_ok:
|
||||
# self.callbacks.on_unreachable(host, exec_rc.result)
|
||||
if not exec_rc.comm_ok:
|
||||
self.callbacks.on_unreachable(host, exec_rc.result)
|
||||
return exec_rc
|
||||
except errors.AnsibleError, ae:
|
||||
msg = str(ae)
|
||||
|
|
Loading…
Reference in a new issue