'mirror' parameter is supporting now.

packages
Иванов Денис 4 years ago
parent 3ac3973731
commit 2b2af024ba

@ -188,7 +188,7 @@ class ParametersProcessor:
def check_postparse_parameters(self):
for parameter, parameter_checker in\
self.postparse_checkers_list.items():
if not self._parameters_container[parameter]:
if parameter not in self._parameters_container:
continue
parameter_value = self._parameters_container[parameter]
@ -260,7 +260,7 @@ class ParametersProcessor:
if isinstance(parameter_value, bool):
raise IncorrectParameter("'rebuild' parameter value is not bool")
elif 'package' not in self._parameters_container:
raise IncorrectParameter(("'source' parameter is set without "
raise IncorrectParameter(("'rebuild' parameter is set without "
"'package' parameter"))
return parameter_value
@ -336,9 +336,10 @@ class ParametersProcessor:
else:
real_path = parameter_value
# Ставим True, чтобы потом проверить этот параметр в postparse
if not os.path.exists(real_path):
raise IncorrectParameter(
"File from 'source' parameter does not exist")
return True
source_file_type = DIR if os.path.isdir(real_path) else FILE
if not parameter_value or isinstance(parameter_value, bool):
@ -347,7 +348,8 @@ class ParametersProcessor:
if (self._parameters_container.append == 'link' and
self.template_type != source_file_type):
raise IncorrectParameter(
"the type of the 'source' file does not match")
"the type of the 'source' file does not match"
" the type of the template file")
return os.path.normpath(real_path)
@ -385,6 +387,8 @@ class ParametersProcessor:
raise IncorrectParameter(
"'autoupdate' parameter value is not bool")
# Методы для проверки параметров после разбора всего шаблона.
def check_postparse_append(self, parameter_value):
if parameter_value == 'link':
if 'source' not in self._parameters_container:
@ -392,9 +396,16 @@ class ParametersProcessor:
"parameter.")
def check_postparse_source(self, parameter_value):
if (self.template_type == DIR and
('append' not in self._parameters_container or
self._parameters_container['append'] != 'link')):
# Если файл по пути source не существует, но присутствует параметр
# mirror -- пропускаем шаблон для того, чтобы целевой файл мог быть
# удален в исполнительном модуле.
if parameter_value is True:
if not self._parameters_container.mirror:
raise IncorrectParameter(
"File from 'source' parameter does not exist")
elif (self.template_type == DIR and
('append' not in self._parameters_container or
self._parameters_container['append'] != 'link')):
raise IncorrectParameter(
("'source' parameter is set without "
"append = 'link' for directory template")
@ -657,6 +668,9 @@ class ParametersContainer(MutableMapping):
return '<ParametersContainer: parameters={0}, inheritables={1}>'.\
format(self.__parameters, self.__inheritable)
def __contains__(self, name):
return name in self.__parameters or name in self.__inheritable
@property
def parameters(self):
return self.__parameters

@ -720,7 +720,7 @@ class Package:
'''Метод для удаления файлов и ссылок.'''
file_path = self.remove_chroot_path(file_path)
if file_path in self.contents_dictionary:
self.contents_dictionary.remove(file_path)
self.contents_dictionary.pop(file_path)
def remove_dir(self, file_path):
'''Метод для удаления из CONTENTS файлов и директорий находящихся
@ -728,7 +728,7 @@ class Package:
directory_path = self.remove_chroot_path(file_path)
for file_path in self.contents_dictionary:
if file_path.startswith(directory_path):
self.contents_dictionary.remove(file_path)
self.contents_dictionary.pop(file_path)
def clear_dir(self, file_path):
'''Метод для удаления из CONTENTS файлов и директорий находящихся
@ -738,7 +738,7 @@ class Package:
if file_path == directory_path:
continue
if file_path.startswith(directory_path):
self.contents_dictionary.remove(file_path)
self.contents_dictionary.pop(file_path)
def remove_empty_directories(self):
'''Метод для удаления из CONTENTS директорий, которые после удаления
@ -753,9 +753,14 @@ class Package:
while file_directory != '/':
used_directories.add(file_directory)
file_directory = os.path.dirname(file_directory)
for filepath, value in self.contents_dictionary.items():
if value['type'] == 'dir' and filepath not in used_directories:
self.contents_dictionary.remove(filepath)
paths_to_delete = [file_path for file_path, value in
self.contents_dictionary.items()
if value['type'] == 'dir' and
file_path not in used_directories]
for file_path in paths_to_delete:
self.contents_dictionary.pop(file_path)
def get_md5(self, file_path):
'''Метод для получения md5 хэш-суммы указанного файла.'''

@ -12,7 +12,7 @@ import glob
import shutil
import os
template_text = '''{% calculate append = 'join' -%}
template_text = '''{% calculate append = 'link', source = '/etc/dir/dir_2' -%}
{% calculate package = 'test-category/test-package', format = 'samba' -%}
[section one]
parameter_1 = {{ vars_1.value_1 }}
@ -20,10 +20,12 @@ parameter_1 = {{ vars_1.value_1 }}
'''
backup_template_text = '''{% calculate append = 'join', format = 'samba',
autoupdate -%}
autoupdate, package = 'test-category/test-package' -%}
[section one]
parameter_1 = value
parameter_2 = value_2
[section two]
other_parameter = other_value
'''
APPENDS_SET = TemplateAction().available_appends
@ -56,6 +58,7 @@ class TemplateCollisionError(Exception):
class CalculateConfigFile:
'''Класс для работы с файлом /var/lib/calculate/config.'''
def __init__(self, cl_config_path='/var/lib/calculate/config',
cl_chroot_path='/'):
self.chroot_path = cl_chroot_path
@ -71,6 +74,7 @@ class CalculateConfigFile:
return file_path in self._config_dictionary
def _get_cl_config_dictionary(self):
'''Метод для загрузки словаря файла /var/lib/calculate/config.'''
config_dictionary = OrderedDict()
if os.path.exists(self.cl_config_path):
@ -98,17 +102,21 @@ class CalculateConfigFile:
return config_dictionary
def set_files_md5(self, file_path, file_md5):
'''Метод для установки в config соответствия файла некоторой
контрольной сумме.'''
file_path = self._remove_chroot(file_path)
self._config_dictionary[file_path] = file_md5
self._unsaved_changes = True
def remove_file(self, file_path):
'''Метод для удаления файла из config.'''
file_path = self._remove_chroot(file_path)
if file_path in self._config_dictionary:
self._config_dictionary.pop(file_path)
self._unsaved_changes = True
def compare_md5(self, file_path, file_md5):
'''Метод для сравнения хэш-суммы из config и некоторой заданной.'''
file_path = self._remove_chroot(file_path)
if file_path in self._config_dictionary:
return self._config_dictionary[file_path] == file_md5
@ -116,6 +124,7 @@ class CalculateConfigFile:
return False
def save_changes(self):
'''Метод для записи изменений, внессенных в файл config.'''
if not self._unsaved_changes:
return
config_file = write_file(self.cl_config_path)
@ -127,6 +136,7 @@ class CalculateConfigFile:
self._unsaved_changes = False
def _remove_chroot(self, file_path):
'''Метод для удаления корневого пути из указанного пути.'''
if self.chroot_path != '/' and file_path.startswith(self.chroot_path):
file_path = file_path[len(self.chroot_path):]
@ -201,7 +211,14 @@ class TemplateWrapper:
self.target_type = file_type
break
self.target_is_link = os.path.islink(target_path)
# Если установлен параметр mirror и есть параметр source,
# содержащий несуществующий путь -- удаляем целевой файл.
if self.parameters.source is True and self.parameters.mirror:
self.remove_original = True
else:
if self.parameters.mirror:
raise TemplateExecutorError("target file does not exist, while"
" 'mirror' parameter is set")
self.target_type = None
self.check_conflicts()
@ -313,7 +330,7 @@ class TemplateWrapper:
'''Метод для проверки наличия пользовательских изменений в
конфигурационных файлах.'''
# Эта проверка только для файлов.
if self.target_type != FILE:
if self.template_type != FILE:
return
# Проверим, является ли файл защищенным.
@ -328,8 +345,6 @@ class TemplateWrapper:
self.protected = False
break
print('Is protected:', self.protected)
# Собираем список имеющихся ._cfg файлов.
cfg_pattern = os.path.join(os.path.dirname(self.target_path),
"._cfg????_{}".format(
@ -418,9 +433,11 @@ class TemplateWrapper:
def remove_from_contents(self):
'''Метод для удаления целевого файла из CONTENTS.'''
print('let s remove')
if self.template_type == DIR:
self.target_package.remove_dir(self.target_path)
elif self.template_type == FILE:
print('remove as file')
self.target_package.remove_obj(self.target_path)
def clear_dir_contents(self):
@ -443,6 +460,7 @@ class TemplateWrapper:
'''Метод для получения множества защищенных директорий.'''
if cls._protected_is_set:
return
cls._protected_set = set()
cls._protected_set.add(join_paths(cls.chroot_path, '/etc'))
@ -464,7 +482,9 @@ class TemplateWrapper:
def save_changes(self):
'''Метод для сохранения изменений внесенных в CONTENTS.'''
if self.target_package and not self.parameters.unbound:
if self.target_package:
print('saving CONTENTS: {}'.format(
self.target_package.contents_dictionary.keys()))
self.target_package.remove_empty_directories()
self.target_package.write_contents_file()
@ -515,19 +535,31 @@ class TemplateExecutor:
template_type,
template_text=template_text)
except TemplateTypeConflict as error:
print('Error: {}'.format(str(error)))
return
except TemplateCollisionError as error:
print('Error: {}'.format(str(error)))
return
# Удаляем оригинал, если это необходимо из-за наличия force или по
# другим причинам.
if template_object.remove_original:
print('remove original')
if template_object.target_type == DIR:
self._remove_directory(template_object.target_path)
else:
self._remove_file(template_object.target_path)
template_object.remove_from_contents()
# Если был включен mirror, то после удаления файла завершаем
# выполнение шаблона.
if template_object.parameters.mirror:
template_object.save_changes()
return
template_object.target_type = None
print('input path: {}'.format(template_object.input_path))
print('output path: {}'.format(template_object.output_path))
# (!) Добавить поддержку run, execute и т.д.
if template_object.template_type == DIR:
self.directory_appends[template_object.parameters.append](
@ -536,9 +568,10 @@ class TemplateExecutor:
self.file_appends[template_object.parameters.append](
template_object)
# Сохраняем изменения в CONTENTS внесенные согласно шаблону.
print('it is time to save changes')
template_object.save_changes()
# Возвращаем целевой путь, если он был изменен.
# Возвращаем целевой путь, если он был изменен, или None если не был.
if template_object.target_path_is_changed:
return template_object.target_path
else:
@ -650,11 +683,15 @@ class TemplateExecutor:
# Убираем целевой файл из CL.
self.calculate_config_file.remove_file(template_object.target_path)
print('is contents update is needed')
# Обновляем CONTENTS.
if template_object.protected:
print('needed')
if template_object.parameters.unbound:
print('remove')
template_object.remove_from_contents()
else:
print('add')
template_object.add_to_contents(file_md5=output_text_md5)
else:
with open(input_path, 'r') as input_file:
@ -692,8 +729,8 @@ class TemplateExecutor:
# Действия если CL совпало. Пока ничего не делаем.
pass
# Обновляем CONTENTS.
template_object.add_to_contents(file_md5=output_text_md5)
# Обновляем CONTENTS.
template_object.add_to_contents(file_md5=output_text_md5)
def _create_directory(self, template_object: TemplateWrapper):
'''Метод для создания директории и, при необходимости, изменения
@ -954,6 +991,7 @@ template_executor_obj.execute_template(target_path,
template_parameters,
FILE, template_text=template_text)
template_executor_obj.save_changes()
input()
template_engine.process_template_from_string(backup_template_text, FILE)
template_parameters = template_engine.parameters

@ -0,0 +1,5 @@
[section one]
parameter_1 = value_1
[section two]
parameter_3 = value_3
origin_parameter = origin_value

@ -2,5 +2,4 @@
parameter_1 = value
parameter_2 = value_2
[section two]
parameter_3 = value_3
origin_parameter = origin_value
other_parameter = other_value

@ -1,3 +1,3 @@
dir /etc
dir /etc/dir
obj /etc/dir/file.conf f050e31b0c059cc6b1edbd4871db1b91 1590505223
obj /etc/dir/file.conf 0b87fea7f5b65cac5012baa2bf647e72 1590588845

@ -2,5 +2,4 @@
parameter_1 = value
parameter_2 = value_2
[section two]
parameter_3 = value_3
origin_parameter = origin_value
other_parameter = other_value

Loading…
Cancel
Save