salt/salt/modules/ini_manage.py
2014-01-16 18:17:20 +05:30

358 lines
10 KiB
Python

# -*- coding: utf-8 -*-
'''
:maintainer: <ageeleshwar.kandavelu@csscorp.com>
:maturity: new
:depends: re
:platform: all
Module for editing ini files through saltstack
use section as DEFAULT_IMPLICIT if your ini file does not have any section
for example /etc/sysctl.conf
'''
# Import Python libs
import re
__virtualname__ = 'ini'
def __virtual__():
'''
Rename to ini
'''
return __virtualname__
comment_regexp = re.compile(r'^\s*#\s*(.*)')
section_regexp = re.compile(r'\s*\[(.+)\]\s*')
option_regexp1 = re.compile(r'\s*(.+?)\s*(=)\s*(.+)\s*')
option_regexp2 = re.compile(r'\s*(.+?)\s*(:)\s*(.+)\s*')
def set_option(file_name, sections=None, summary=True):
'''
Edit ini files
file_name: path of ini_file
sections: a dictionary representing the ini file
returns a dictionary containing the changes made
set summary=False if return data need not have previous option value
from api:
import salt
sc = salt.client.LocalClient()
sc.cmd('target', 'ini.set_option',
['path_to_ini_file', '{"section_to_change": {"key": "value"}}'])
CLI Example:
.. code-block:: bash
salt '*' ini.set_option /path/to/ini '{section_foo: {key: value}}'
'''
if sections is None:
sections = {}
ret = {'file_name': file_name}
inifile = _Ini.get_ini_file(file_name)
if not inifile:
ret.update({'error': 'ini file not found'})
return ret
changes = {}
err_flag = False
for section in sections:
changes.update({section: {}})
for option in sections[section]:
try:
current_value = get_option(file_name, section, option)
if not current_value == sections[section][option]:
inifile.update_section(section,
option,
sections[section][option])
changes[section].update(
{
option: {
'before': current_value,
'after': sections[section][option]
}
})
if not summary:
changes[section].update({option:
sections[section][option]})
except Exception:
ret.update({'error':
'while setting option {0} in section {0}'.
format(option, section)})
err_flag = True
break
if not err_flag:
inifile.flush()
ret.update({'changes': changes})
return ret
def get_option(file_name, section, option):
'''
Get value of a key from a section in a ini file
from api:
import salt
sc = salt.client.LocalClient()
sc.cmd('target', 'ini.get_option',
[path_to_ini_file, section_name, option])
CLI Example:
.. code-block:: bash
salt '*' ini.get_option /path/to/ini section_name option_name
'''
inifile = _Ini.get_ini_file(file_name)
if inifile:
opt = inifile.get_option(section, option)
if opt:
return opt.value
def remove_option(file_name, section, option):
'''
Remove a key,value pair from a section in a ini file
returns the value of the removed key
from api:
import salt
sc = salt.client.LocalClient()
sc.cmd('target', 'ini.remove_option',
[path_to_ini_file, section_name, option])
CLI Example:
.. code-block:: bash
salt '*' ini.remove_option /path/to/ini section_name option_name
'''
inifile = _Ini.get_ini_file(file_name)
if inifile:
opt = inifile.remove_option(section, option)
if opt:
inifile.flush()
return opt.value
def get_section(file_name, section):
'''
get a section in a ini file
returns the section as dictionary
from api:
import salt
sc = salt.client.LocalClient()
sc.cmd('target', 'ini.get_section',
[path_to_ini_file, section_name])
CLI Example:
.. code-block:: bash
salt '*' ini.get_section /path/to/ini section_name
'''
inifile = _Ini.get_ini_file(file_name)
if inifile:
sect = inifile.get_section(section)
if sect:
return sect.contents()
def remove_section(file_name, section):
'''
remove a section in a ini file
returns the removed section as dictionary
from api:
import salt
sc = salt.client.LocalClient()
sc.cmd('target', 'ini.remove_section',
[path_to_ini_file, section_name])
CLI Example:
.. code-block:: bash
salt '*' ini.remove_section /path/to/ini section_name
'''
inifile = _Ini.get_ini_file(file_name)
if inifile:
sect = inifile.remove_section(section)
if sect:
inifile.flush()
return sect.contents()
class _Section(list):
def __init__(self, name):
super(_Section, self).__init__()
self.section_name = name
def get_option(self, option_name):
for item in self:
if isinstance(item, _Option) and (item.name == option_name):
return item
def update_option(self, option_name, option_value=None, separator="="):
option_to_update = self.get_option(option_name)
if not option_to_update:
option_to_update = _Option(option_name)
self.append(option_to_update)
option_to_update.value = option_value
option_to_update.separator = separator
def remove_option(self, option_name):
option_to_remove = self.get_option(option_name)
if option_to_remove:
return self.pop(self.index(option_to_remove))
def contents(self):
contents = {}
for item in self:
try:
contents.update({item.name: item.value})
except Exception:
pass # item was a comment
return contents
def __nonzero__(self):
return True
def __eq__(self, item):
return (isinstance(item, self.__class__) and
self.section_name == item.section_name)
def __ne__(self, item):
return not (isinstance(item, self.__class__) and
self.section_name == item.section_name)
class _Option(object):
def __init__(self, name, value=None, separator="="):
super(_Option, self).__init__()
self.name = name
self.value = value
self.separator = separator
def __eq__(self, item):
return (isinstance(item, self.__class__) and
self.name == item.name)
def __ne__(self, item):
return not (isinstance(item, self.__class__) and
self.name == item.name)
class _Ini(object):
def __init__(self, file_name):
super(_Ini, self).__init__()
self.file_name = file_name
def refresh(self):
self.sections = []
current_section = _Section('DEFAULT_IMPLICIT')
self.sections.append(current_section)
with open(self.file_name, 'r') as inifile:
for line in inifile.readlines():
if _Ini.iscomment(line):
current_section.append(_Ini.decrypt_comment(line))
elif _Ini.isnewsection(line):
self.sections.append(_Ini.decrypt_section(line))
current_section = self.sections[-1]
elif _Ini.isoption(line):
current_section.append(_Ini.decrypt_option(line))
return self
def flush(self):
with open(self.file_name, 'w') as outfile:
outfile.write(self.current_contents())
def dump(self):
print self.current_contents()
def current_contents(self):
file_contents = ''
for section in self.sections:
if not section.section_name == 'DEFAULT_IMPLICIT':
file_contents += '[%s]\n' % section.section_name
for item in section:
if isinstance(item, _Option):
file_contents += '%s%s%s\n' % (item.name, item.separator,
item.value)
else:
file_contents += '# %s\n' % item
file_contents += '\n'
return file_contents
def get_section(self, section_name):
for section in self.sections:
if section.section_name == section_name:
return section
def get_option(self, section_name, option):
section_to_get = self.get_section(section_name)
if section_to_get:
return section_to_get.get_option(option)
def update_section(self, section_name, option_name=None,
option_value=None, separator="="):
section_to_update = self.get_section(section_name)
if not section_to_update:
section_to_update = _Section(section_name)
self.sections.append(section_to_update)
if option_name:
section_to_update.update_option(option_name, option_value,
separator)
def remove_section(self, section_name):
section_to_remove = self.get_section(section_name)
if section_to_remove:
return self.sections.pop(self.sections.index(section_to_remove))
def remove_option(self, section_name, option_name):
section_to_update = self.get_section(section_name)
if section_to_update:
return section_to_update.remove_option(option_name)
@staticmethod
def decrypt_comment(line):
ma = re.match(comment_regexp, line)
return ma.group(1).strip()
@staticmethod
def decrypt_section(line):
ma = re.match(section_regexp, line)
return _Section(ma.group(1).strip())
@staticmethod
def decrypt_option(line):
ma = re.match(option_regexp1, line)
if not ma:
ma = re.match(option_regexp2, line)
return _Option(ma.group(1).strip(), ma.group(3).strip(),
ma.group(2).strip())
@staticmethod
def iscomment(line):
return re.match(comment_regexp, line)
@staticmethod
def isnewsection(line):
return re.match(section_regexp, line)
@staticmethod
def isoption(line):
return re.match(option_regexp1, line) or re.match(option_regexp2, line)
@staticmethod
def get_ini_file(file_name):
try:
return _Ini(file_name).refresh()
except Exception:
return