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()
|
self._parse_group_variables()
|
||||||
return self.groups
|
return self.groups
|
||||||
|
|
||||||
|
|
||||||
# [webservers]
|
# [webservers]
|
||||||
# alpha
|
# alpha
|
||||||
# beta:2345
|
# beta:2345
|
||||||
|
|
|
@ -20,12 +20,16 @@ from ansible.inventory.host import Host
|
||||||
from ansible.inventory.group import Group
|
from ansible.inventory.group import Group
|
||||||
from ansible import errors
|
from ansible import errors
|
||||||
from ansible import utils
|
from ansible import utils
|
||||||
|
import sys
|
||||||
|
|
||||||
class InventoryParserYaml(object):
|
class InventoryParserYaml(object):
|
||||||
''' Host inventory parser for ansible '''
|
''' Host inventory parser for ansible '''
|
||||||
|
|
||||||
def __init__(self, filename=C.DEFAULT_HOST_LIST):
|
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)
|
fh = open(filename)
|
||||||
data = fh.read()
|
data = fh.read()
|
||||||
fh.close()
|
fh.close()
|
||||||
|
|
|
@ -508,8 +508,8 @@ class Runner(object):
|
||||||
if type(exec_rc) != ReturnData:
|
if type(exec_rc) != ReturnData:
|
||||||
raise Exception("unexpected return type: %s" % type(exec_rc))
|
raise Exception("unexpected return type: %s" % type(exec_rc))
|
||||||
# redundant, right?
|
# redundant, right?
|
||||||
#if not exec_rc.comm_ok:
|
if not exec_rc.comm_ok:
|
||||||
# self.callbacks.on_unreachable(host, exec_rc.result)
|
self.callbacks.on_unreachable(host, exec_rc.result)
|
||||||
return exec_rc
|
return exec_rc
|
||||||
except errors.AnsibleError, ae:
|
except errors.AnsibleError, ae:
|
||||||
msg = str(ae)
|
msg = str(ae)
|
||||||
|
|
Loading…
Reference in a new issue