Compare commits
36 Commits
5e3ff68325
...
release/0.
Author | SHA1 | Date | |
---|---|---|---|
534b5f4413 | |||
5a1c39e8a1 | |||
8d09b90d26 | |||
a97c17a615 | |||
8e22886938 | |||
0b98f2ff6f | |||
5c3ab2ae17 | |||
d139862568 | |||
9bb1a8c26a | |||
d8e99fef54 | |||
25d5307415 | |||
963e93295a | |||
1c5ab706ed | |||
a542b2bfdc | |||
2207537b64 | |||
509bf21d08 | |||
3eb208b2c1 | |||
5952a8d759 | |||
d86744d1cf | |||
1ce16ad05d | |||
3881cb7e98 | |||
81028d1539 | |||
2f8fc054d0 | |||
f19a427f46 | |||
f062d9f30a | |||
881b551f47 | |||
9ec8f881ab | |||
cbf107cbdc | |||
024fecddbb | |||
729b35d372 | |||
1b65d22eaa | |||
1a3632f577 | |||
06535b42b8 | |||
79a7950b0b | |||
96e392cfd8 | |||
498e950610 |
24
Makefile
24
Makefile
@ -1,24 +0,0 @@
|
||||
################################
|
||||
# Makefile pour creole
|
||||
################################
|
||||
|
||||
SOURCE=creole
|
||||
EOLE_VERSION=2.7
|
||||
EOLE_RELEASE=2.7.0
|
||||
|
||||
################################
|
||||
# Début de zone à ne pas éditer
|
||||
################################
|
||||
|
||||
include eole.mk
|
||||
include apps.mk
|
||||
|
||||
################################
|
||||
# Fin de zone à ne pas éditer
|
||||
################################
|
||||
|
||||
# Makefile rules dedicated to application
|
||||
# if exists
|
||||
ifneq (, $(strip $(wildcard $(SOURCE).mk)))
|
||||
include $(SOURCE).mk
|
||||
endif
|
64
apps.mk
64
apps.mk
@ -1,64 +0,0 @@
|
||||
#
|
||||
# NE PAS EDITER CE FICHIER
|
||||
#
|
||||
# Voir Makefile
|
||||
|
||||
|
||||
##########################
|
||||
# Application web envole #
|
||||
##########################
|
||||
ifneq (, $(filter oui web, $(PKGAPPS)))
|
||||
#
|
||||
# Sanity check
|
||||
#
|
||||
ifeq (, $(filter-out X.X, $(strip $(VERSION))))
|
||||
$(error $$(VERSION) variable has incorrect value '$(VERSION)')
|
||||
endif
|
||||
|
||||
# Where to store web application files
|
||||
WEB_PATH := $(DESTDIR)/var/www/html
|
||||
|
||||
# Envole
|
||||
sharenvole_PROG_DIR := $(DESTDIR)/usr/share/envole/$(SOURCE)
|
||||
|
||||
src_$(SOURCE)-$(VERSION)_REC_DIR := $(WEB_PATH)/$(SOURCE)
|
||||
src_plugins-$(VERSION)_REC_DIR := $(WEB_PATH)/$(SOURCE)/plugin
|
||||
src_lang-$(VERSION)_REC_DIR := $(WEB_PATH)/$(SOURCE)/lang
|
||||
|
||||
endif
|
||||
|
||||
##########################
|
||||
# Application EOLE flask #
|
||||
##########################
|
||||
ifneq (, $(filter flask, $(PKGAPPS)))
|
||||
#
|
||||
# Sanity check
|
||||
#
|
||||
ifeq (, $(filter-out XXX, $(strip $(FLASK_MODULE))))
|
||||
$(error $$(FLASK_MODULE) variable has incorrect value '$(FLASK_MODULE)')
|
||||
endif
|
||||
|
||||
ifeq (, $(strip $(wildcard src/$(FLASK_MODULE).conf)))
|
||||
$(error missing eoleflask configuration file 'src/$(FLASK_MODULE).conf')
|
||||
endif
|
||||
|
||||
# Everything is related to mount point
|
||||
APPS_MOUNT_POINT := $(shell sed -ne 's|^"MOUNT_POINT"[[:space:]]*:[[:space:]]*"/\([^"]*\)",|\1|p' \
|
||||
src/$(FLASK_MODULE).conf)
|
||||
|
||||
ifeq (, $(strip $(APPS_MOUNT_POINT)))
|
||||
$(error no "MOUNT_POINT" in eoleflask configuration file 'src/$(FLASK_MODULE).conf')
|
||||
endif
|
||||
|
||||
# eole-flask configuration
|
||||
src_DATA_DIR := $(DESTDIR)/etc/eole/flask/available
|
||||
|
||||
# Where to store flask application files
|
||||
FLASK_PATH := $(eole_DIR)/flask/$(APPS_MOUNT_POINT)
|
||||
|
||||
# static files
|
||||
src_$(FLASK_MODULE)_static_REC_DIR := $(FLASK_PATH)/static
|
||||
src_$(FLASK_MODULE)_templates_REC_DIR := $(FLASK_PATH)/templates
|
||||
src_$(FLASK_MODULE)_instance_REC_DIR := $(FLASK_PATH)/resources
|
||||
|
||||
endif
|
15
creole.mk
15
creole.mk
@ -1,15 +0,0 @@
|
||||
# creole specific rules
|
||||
|
||||
schedule_PROG_DIR := $(eole_DIR)/schedule
|
||||
upgrade_REC_DIR := $(eole_DIR)/upgrade
|
||||
bin_PROG_DIR := $(DESTDIR)/usr/bin
|
||||
sbin_PROG_DIR := $(DESTDIR)/usr/sbin
|
||||
data_REC_DIR := $(DESTDIR)/usr/share/creole
|
||||
fr.man8_DATA_DIR := $(DESTDIR)/usr/share/man/fr.UTF-8/man8
|
||||
en.man8_DATA_DIR := $(DESTDIR)/usr/share/man/man8
|
||||
motd_PROG_DIR := $(DESTDIR)/etc/update-motd.d
|
||||
local_DATA_DIR := $(DESTDIR)/usr/share/eole/creole/dicos/local
|
||||
|
||||
install-files::
|
||||
# To inform user about coding changes
|
||||
$(INSTALL_DATA) deprecated/FonctionsEoleNg $(eole_DIR)
|
@ -1,25 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
fichier de configuration pour créole
|
||||
|
||||
"""
|
||||
from os.path import join, isfile
|
||||
|
||||
eoledir = '/usr/share/eole'
|
||||
|
||||
eoleroot = join(eoledir, 'creole')
|
||||
|
||||
# chemin du répertoire source des fichiers templates
|
||||
templatedir = '/var/lib/creole'
|
||||
|
||||
distrib_dir = join(eoleroot, 'distrib')
|
||||
patch_dir = join(eoleroot, 'patch')
|
||||
|
||||
# repertoire de la dtd
|
||||
dtddir = '/usr/share/creole'
|
||||
if isfile('data/creole.dtd'):
|
||||
dtdfilename = 'data/creole.dtd'
|
||||
elif isfile('../creole/data/creole.dtd'):
|
||||
dtdfilename = '../creole/data/creole.dtd'
|
||||
else:
|
||||
dtdfilename = join(dtddir, 'creole.dtd')
|
@ -1,14 +0,0 @@
|
||||
XXX: Currently in progress, NOT IN WORKING STATE.
|
||||
|
||||
MAJOR REASON IS :
|
||||
**revamping the implementation entirely for scalability**
|
||||
|
||||
AND :
|
||||
NOT INTEGRATED YET
|
||||
for pretty print in the console
|
||||
- ansiprint.py
|
||||
- terminalreport.py
|
||||
- terminalwriter.py
|
||||
|
||||
|
||||
|
@ -1,78 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Simple API fro creolelint reports"""
|
||||
import sys
|
||||
from creole.lint.warning import Warn
|
||||
from creole.lint import warnsymb
|
||||
|
||||
def ansi_print(text=None, fhandle=None, newline=True, flush=False):
|
||||
"""normalized (ansi) print >> file handle function"""
|
||||
#sys.stdout.write(self.getvalue())
|
||||
if fhandle is None:
|
||||
fhandle = sys.stderr
|
||||
if text != None:
|
||||
#text = text.strip()
|
||||
if newline:
|
||||
text += '\n'
|
||||
fhandle.write(text)
|
||||
if flush:
|
||||
fhandle.flush()
|
||||
# if fhandle:
|
||||
# fhandle.close()
|
||||
|
||||
class AnsiWriter(object):
|
||||
"""Définit une interface d'écriture de warnings
|
||||
"""
|
||||
def __init__(self, write_level, output=sys.stdout):
|
||||
self.write_level = write_level
|
||||
self.output = output
|
||||
|
||||
def process(self, linter):
|
||||
"""
|
||||
parse a result from an item.check() dictionnary
|
||||
which is made of {name: TmplVar}
|
||||
"""
|
||||
ident=1
|
||||
itemname = linter.name
|
||||
warnno = linter.warnno
|
||||
warncomment = linter.warncomment
|
||||
display = linter.display
|
||||
name, level = warnsymb.errorcode[warnno]
|
||||
if level > getattr(warnsymb, self.write_level):
|
||||
print "\nLint {0} désactivé (niveau {1})".format(itemname, warnsymb.errorlevel[level])
|
||||
return ''
|
||||
level = warnsymb.errorlevel[level]
|
||||
if not display:
|
||||
ansi_print('')
|
||||
ansi_print('%s (%s:%s:%s)'%(warncomment, itemname, name, level), self.output)
|
||||
checks = linter.check()
|
||||
warn = Warn(self.write_level, itemname, warnno, warncomment, checks)
|
||||
dico_loc = warn.to_dict()
|
||||
if dico_loc != '' and dico_loc != {}:
|
||||
ansi_print('')
|
||||
ansi_print('%s (%s:%s:%s)'%(warncomment, itemname, name, level), self.output)
|
||||
def compare(x,y):
|
||||
return cmp(x[0],y[0])
|
||||
for vfile in dico_loc.keys():
|
||||
if vfile != 'dictionnaire':
|
||||
ansi_print('%s\-- fichier %s' % (' '*ident, vfile), self.output, newline=False)
|
||||
vlines = dico_loc[vfile]
|
||||
vlines.sort(compare)
|
||||
oldline=0
|
||||
for vline, var in vlines:
|
||||
if hasattr(var, 'name'):
|
||||
vname = '%%%%%s'%str(var.name)
|
||||
else:
|
||||
vname = str(var)
|
||||
if vline != None:
|
||||
if vline != oldline:
|
||||
ansi_print('', self.output)
|
||||
ansi_print('%s|-- ligne %s' % (' '*(ident+1), vline), self.output, newline=False)
|
||||
pass
|
||||
oldline=vline
|
||||
if vfile != 'dictionnaire':
|
||||
ansi_print(" %s" %vname, self.output, newline=False)
|
||||
else:
|
||||
ansi_print("%s\-- %s" %(' '*ident, vname), self.output)
|
||||
if vfile != 'dictionnaire':
|
||||
ansi_print('', self.output)
|
||||
|
@ -1,39 +0,0 @@
|
||||
"a system command launcher"
|
||||
|
||||
import os, sys
|
||||
import subprocess
|
||||
from subprocess import Popen, PIPE
|
||||
|
||||
def cmdexec(cmd):
|
||||
""" return output of executing 'cmd' in a separate process.
|
||||
|
||||
raise ExecutionFailed exception if the command failed.
|
||||
the exception will provide an 'err' attribute containing
|
||||
the error-output from the command.
|
||||
"""
|
||||
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
out, err = process.communicate()
|
||||
status = process.poll()
|
||||
if status:
|
||||
raise ExecutionFailed(status, status, cmd, out, err)
|
||||
return out
|
||||
|
||||
class ExecutionFailed(Exception):
|
||||
def __init__(self, status, systemstatus, cmd, out, err):
|
||||
Exception.__init__(self)
|
||||
self.status = status
|
||||
self.systemstatus = systemstatus
|
||||
self.cmd = cmd
|
||||
self.err = err
|
||||
self.out = out
|
||||
|
||||
def __str__(self):
|
||||
return "ExecutionFailed: %d %s\n%s" %(self.status, self.cmd, self.err)
|
||||
|
||||
# export the exception under the name 'Error'
|
||||
Error = ExecutionFailed
|
||||
try:
|
||||
ExecutionFailed.__module__ = 'cmdexec'
|
||||
ExecutionFailed.__name__ = 'Error'
|
||||
except (AttributeError, TypeError):
|
||||
pass
|
@ -1,1195 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
creole lint main module
|
||||
"""
|
||||
import types
|
||||
import sys
|
||||
import re
|
||||
from glob import glob
|
||||
from os.path import join, basename, isfile, abspath, normpath, isabs
|
||||
from lxml.etree import parse
|
||||
|
||||
from creole import config, eosfunc
|
||||
from pyeole.process import system_code
|
||||
from creole.lint.parsetemplate import parse_templates
|
||||
from creole.lint.normalize import is_correct
|
||||
from creole.var_loader import parse_dtd
|
||||
from creole.lxml_parser import parse_xml_file
|
||||
from creole.config import FLATTENED_CREOLE_DIR, dtdfilename
|
||||
from creole.loader import PopulateTiramisuObjects
|
||||
|
||||
# variables internes aux dictionnaires
|
||||
DICO_TEST_VARS = ['test_', 'tmp_']
|
||||
# variables de conteneur calculées dynamiquement
|
||||
CONTAINER_VARS = ['container_path_', 'container_ip_', 'container_name_',
|
||||
'adresse_ip_ftp', 'adresse_ip_mysql', 'adresse_ip_dhcp',
|
||||
'adresse_ip_internet', 'adresse_ip_interbase',
|
||||
'adresse_ip_postgresql']
|
||||
|
||||
# faux-positifs sur les variables d'activation
|
||||
EXCLUDE_ACTIVATION_VARS = ['activer_cntlm_eth0', 'activer_cntlm_eth1',
|
||||
'activer_cntlm_eth2', 'activer_cntlm_eth3',
|
||||
'activer_cntlm_eth4', 'activer_supp_proxy_eth0',
|
||||
'activer_bash_completion', 'activer_log_martian',
|
||||
'activer_dns_eth0', 'activer_ctrl_alt_suppr',
|
||||
'activer_ipv6', 'activer_courier_commun',
|
||||
'activer_web_valider_ca', 'activer_admin_passfile',
|
||||
'activer_regles_filtrage_port_source',
|
||||
'activer_ftp_anonymous_access', 'activer_ftp_access',
|
||||
'activer_pydio_local', 'activer_courier_imap_sso',
|
||||
'activer_pydio_ftp', 'activer_client_ldap',
|
||||
]
|
||||
|
||||
# templates à ne pas tester par défaut
|
||||
EXCLUDE_TMPL = ['/usr/share/eole/creole/distrib/named.conf',
|
||||
'/usr/share/eole/creole/distrib/common-squid1.conf',
|
||||
'/usr/share/eole/creole/distrib/zstats.cfg',
|
||||
'/usr/share/eole/creole/distrib/hosts',
|
||||
'/usr/share/eole/creole/distrib/active_tags',
|
||||
]
|
||||
|
||||
# dictionnaires conservés pour compatibilité 2.3
|
||||
OLD_DICOS = ['/usr/share/eole/creole/dicos/51_gepi.xml',
|
||||
'/usr/share/eole/creole/dicos/51_taskfreak.xml',
|
||||
'/usr/share/eole/creole/dicos/51_wordpress.xml',
|
||||
'/usr/share/eole/creole/dicos/60_roundcube.xml',
|
||||
'/usr/share/eole/creole/dicos/61_ajaxplorer.xml',
|
||||
'/usr/share/eole/creole/dicos/61_dokuwiki.xml',
|
||||
'/usr/share/eole/creole/dicos/61_fluxbb.xml',
|
||||
'/usr/share/eole/creole/dicos/61_piwigo.xml',
|
||||
'/usr/share/eole/creole/dicos/51_grr.xml',
|
||||
'/usr/share/eole/creole/dicos/51_cdt.xml',
|
||||
'/usr/share/eole/creole/dicos/51_piwik.xml',
|
||||
'/usr/share/eole/creole/dicos/51_spip.xml',
|
||||
]
|
||||
|
||||
starttoken = '%'
|
||||
varstarttoken = '%%'
|
||||
builts = [u'ArithmeticError', u'AssertionError', u'AttributeError',
|
||||
u'BaseException', u'DeprecationWarning', u'EOFError', u'Ellipsis',
|
||||
u'EnvironmentError', u'Exception', u'False', u'FloatingPointError',
|
||||
u'FutureWarning', u'GeneratorExit', u'IOError', u'ImportError',
|
||||
u'ImportWarning', u'IndentationError', u'IndexError', u'KeyError',
|
||||
u'KeyboardInterrupt', u'LookupError', u'MemoryError', u'NameError',
|
||||
u'None', u'NotImplemented', u'NotImplementedError', u'OSError',
|
||||
u'OverflowError', u'PendingDeprecationWarning', u'ReferenceError',
|
||||
u'RuntimeError', u'RuntimeWarning', u'StandardError',
|
||||
u'StopIteration', u'SyntaxError', u'SyntaxWarning', u'SystemError',
|
||||
u'SystemExit', u'TabError', u'True', u'TypeError',
|
||||
u'UnboundLocalError', u'UnicodeDecodeError', u'UnicodeEncodeError',
|
||||
u'UnicodeError', u'UnicodeTranslateError', u'UnicodeWarning',
|
||||
u'UserWarning', u'ValueError', u'Warning', u'ZeroDivisionError',
|
||||
u'_', u'__debug__', u'__doc__', u'__import__', u'__name__', u'abs',
|
||||
u'all', u'any', u'apply', u'basestring', u'bool', u'buffer',
|
||||
u'callable', u'chr', u'classmethod', u'cmp', u'coerce', u'compile',
|
||||
u'complex', u'copyright', u'credits', u'delattr', u'dict', u'dir',
|
||||
u'divmod', u'enumerate', u'eval', u'execfile', u'exit', u'file',
|
||||
u'filter', u'float', u'frozenset', u'getattr', u'globals',
|
||||
u'hasattr', u'hash', u'help', u'hex', u'id', u'input', u'int',
|
||||
u'intern', u'isinstance', u'issubclass', u'iter', u'len',
|
||||
u'license', u'list', u'locals', u'long', u'map', u'max', u'min',
|
||||
u'object', u'oct', u'open', u'ord', u'pow', u'property', u'quit',
|
||||
u'range', u'raw_input', u'reduce', u'reload', u'repr', u'reversed',
|
||||
u'round', u'set', u'setattr', u'slice', u'sorted', u'staticmethod',
|
||||
u'str', u'sum', u'super', u'tuple', u'type', u'unichr', u'unicode',
|
||||
u'vars', u'xrange', u'zip']
|
||||
builts.append(u'is_defined')
|
||||
builts.append(u'split')
|
||||
builts.append(u'lower')
|
||||
cmd_client = (u'creole_client', ('get', 'get_containers'))
|
||||
for func in dir(eosfunc):
|
||||
if not func.startswith('_'):
|
||||
builts.append(unicode(func, 'utf-8'))
|
||||
|
||||
# FIXME: je sais pas où la mettre
|
||||
def is_container_var(varname):
|
||||
"""
|
||||
variables de conteneur calculées dynamiquement
|
||||
"""
|
||||
for var in CONTAINER_VARS:
|
||||
if varname.startswith(var):
|
||||
return True
|
||||
return False
|
||||
|
||||
class TmplVar():
|
||||
def __init__(self, name, fd, line):
|
||||
self.name = name
|
||||
self.location = []
|
||||
self.add_location(fd, line)
|
||||
|
||||
def add_location(self, fd, line):
|
||||
fd = basename(fd)
|
||||
self.location.append((fd, line+1))
|
||||
|
||||
def set_location(self, location):
|
||||
self.location = location
|
||||
|
||||
def get_location(self):
|
||||
return self.location
|
||||
|
||||
class Var():
|
||||
def __init__(self, name, description, separator, help, defaultvalue, is_slave):
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.separator = separator
|
||||
self.help = help
|
||||
self.defaultvalue = defaultvalue
|
||||
self.is_slave = is_slave
|
||||
|
||||
class CreoleLinter:
|
||||
"""Base class for linters, collects creole vars and templates
|
||||
**has to be launched once and only once**
|
||||
"""
|
||||
display = True
|
||||
class __impl:
|
||||
warnno = 1
|
||||
warncomment = "Undefined comment"
|
||||
""" Implementation of the singleton interface """
|
||||
def set_config(self, tmpl_dir_or_file=None):
|
||||
if tmpl_dir_or_file != None and type(tmpl_dir_or_file) != str:
|
||||
raise TypeError('tmpl_dir_or_file doit être une string')
|
||||
if self.tmpl_dir_or_file != None:
|
||||
sys.stderr('Tentative de redefinition de tmpl_dir_or_file')
|
||||
if tmpl_dir_or_file == None:
|
||||
self.tmpl_dir_or_file = config.distrib_dir
|
||||
else:
|
||||
if not isabs(tmpl_dir_or_file):
|
||||
tmpl_dir_or_file = normpath(join(config.distrib_dir, tmpl_dir_or_file))
|
||||
if not isfile(tmpl_dir_or_file):
|
||||
raise Exception("template doit etre le nom d'un template valide")
|
||||
self.tmpl_dir_or_file = tmpl_dir_or_file
|
||||
self.eoledirs = config.eoledirs
|
||||
self.dtddir = config.dtddir
|
||||
self.exclude_var = []
|
||||
self.pkgname = None
|
||||
|
||||
def load_dics(self):
|
||||
if self.config is None:
|
||||
self._collect_vars_in_dicos()
|
||||
|
||||
# def load_tmpls(self):
|
||||
# if self.tmplvars == None:
|
||||
# self._collect_set_vars()
|
||||
# self._collect_def_vars()
|
||||
# self._collect_for_vars()
|
||||
# self._collect_define_vars()
|
||||
# self._collect_vars_in_tmplfiles()
|
||||
#
|
||||
def get_dicos_name(self):
|
||||
if self.config is None:
|
||||
raise Exception('Dictionnaire non chargé')
|
||||
dic = self.variables.keys()
|
||||
dic.sort()
|
||||
return dic
|
||||
|
||||
# def get_dicos_files(self):
|
||||
# if self.creoledic == None:
|
||||
# raise Exception('Dictionnaire non chargé')
|
||||
# dic = []
|
||||
# for name in self.creoledic.generic['files']:
|
||||
# dic.append(basename(name['source']))
|
||||
# dic.sort()
|
||||
# return dic
|
||||
#
|
||||
# def get_tmplvars_name(self):
|
||||
# if self.tmplvars == None:
|
||||
# raise Exception('Template non chargé')
|
||||
# tmpl = self.tmplvars.keys()
|
||||
# tmpl.sort()
|
||||
# return tmpl
|
||||
#
|
||||
# def get_defvars_name(self):
|
||||
# if self.defvars == None:
|
||||
# raise Exception('Template non chargé')
|
||||
# defv = self.defvars.keys()
|
||||
# defv.sort()
|
||||
# return defv
|
||||
#
|
||||
# def get_setvars_name(self):
|
||||
# if self.setvars == None:
|
||||
# raise Exception('Fonction non chargé')
|
||||
# var = self.setvars.keys()
|
||||
# var.sort()
|
||||
# return var
|
||||
#
|
||||
# def get_forvars_name(self):
|
||||
# if self.forvars == None:
|
||||
# raise Exception('Fonction non chargé')
|
||||
# var = self.forvars.keys()
|
||||
# var.sort()
|
||||
# return var
|
||||
#
|
||||
# def get_tmplvar(self, name):
|
||||
# return self.tmplvars[name]
|
||||
#
|
||||
# def get_separators(self):
|
||||
# return self.creoledic.get_separators()
|
||||
#
|
||||
def get_dico_file_names(self):
|
||||
if self.eoledirs == None or self.tmpl_dir_or_file == None:
|
||||
raise Exception('Utiliser la methode set_config avant')
|
||||
ret = []
|
||||
for eoledir in self.eoledirs:
|
||||
eoledir = abspath(eoledir)
|
||||
if isfile(eoledir):
|
||||
ret.append(eoledir)
|
||||
else:
|
||||
ret.extend(glob(join(eoledir, '*.xml')))
|
||||
return ret
|
||||
|
||||
def get_dtd(self):
|
||||
if self.dtddir == None:
|
||||
raise Exception('Utiliser la methode set_config avant')
|
||||
return join(self.dtddir, 'creole.dtd')
|
||||
|
||||
def _collect_vars_in_dicos(self):
|
||||
if self.eoledirs == None or self.tmpl_dir_or_file == None:
|
||||
raise Exception('Utiliser la methode set_config avant')
|
||||
|
||||
flattened = join(FLATTENED_CREOLE_DIR, 'flattened_creole.xml')
|
||||
with file(flattened, 'r') as fhd:
|
||||
xmlroot = parse(fhd).getroot()
|
||||
tiramisu_objects = PopulateTiramisuObjects()
|
||||
tiramisu_objects.parse_dtd(dtdfilename)
|
||||
tiramisu_objects.make_tiramisu_objects(xmlroot)
|
||||
self.config = tiramisu_objects.build()
|
||||
|
||||
self.config.read_write()
|
||||
self.config.cfgimpl_get_settings().remove('hidden')
|
||||
self.config.cfgimpl_get_settings().remove('validator')
|
||||
self.config.cfgimpl_get_settings().remove('disabled')
|
||||
for path in self.config.creole.make_dict():
|
||||
spath = path.split('.')
|
||||
vname = spath[-1]
|
||||
fname = spath[0]
|
||||
is_slave = False
|
||||
if len(spath) == 3:
|
||||
master = spath[1]
|
||||
if master != vname:
|
||||
is_slave = True
|
||||
option = self.config.unwrap_from_path('creole.' + path)
|
||||
self.variables[vname] = Var(vname, option.impl_get_information('doc', None),
|
||||
option.impl_get_information('separator', ''),
|
||||
option.impl_get_information('help', None),
|
||||
option.impl_getdefault(),
|
||||
is_slave)
|
||||
if fname not in self.families:
|
||||
self.families.append(fname)
|
||||
|
||||
def _parse_tabs_in_dicos(self):
|
||||
if self.eoledirs == None or self.tmpl_dir_or_file == None:
|
||||
raise Exception('Utiliser la methode set_config avant')
|
||||
tabs_in_dics = []
|
||||
fnames = []
|
||||
for directory in self.eoledirs:
|
||||
if isfile(directory):
|
||||
fnames.append(directory)
|
||||
else:
|
||||
fnames.extend(glob(join(directory, "*.xml")))
|
||||
for fname in fnames:
|
||||
fh = file(fname, 'r')
|
||||
content = fh.read()
|
||||
if '\t' in content:
|
||||
tabs_in_dics.append(fname)
|
||||
fh.close()
|
||||
return tabs_in_dics
|
||||
|
||||
def _list_tmpl_files(self):
|
||||
if isfile(self.tmpl_dir_or_file):
|
||||
return [self.tmpl_dir_or_file]
|
||||
ret = []
|
||||
for filename in glob(join(self.tmpl_dir_or_file, '*')):
|
||||
if filename.startswith('.') or filename.endswith('~'):
|
||||
continue
|
||||
if filename in EXCLUDE_TMPL:
|
||||
print " \\-- template desactivé : {0}".format(filename)
|
||||
continue
|
||||
ret.append(filename)
|
||||
return ret
|
||||
|
||||
# def _add_collected_var(self, dvar, var, fd, linenb):
|
||||
# if dvar.has_key(var):
|
||||
# dvar[var].add_location(fd=fd, line=linenb)
|
||||
# else:
|
||||
# dvar[var] = TmplVar(name=var, fd=fd, line=linenb)
|
||||
#
|
||||
# def _collect_var_in(self, dvar, var, fd, linenb, exists=False):
|
||||
# not_added=True
|
||||
# if exists == True:
|
||||
# if self.forvars.has_key(var):
|
||||
# #si deja en memoire
|
||||
# if (basename(fd), linenb+1) in self.forvars[var].location:
|
||||
# return
|
||||
# self._add_collected_var(self.forvars, var, fd, linenb)
|
||||
# not_added=False
|
||||
# if self.setvars.has_key(var):
|
||||
# self._add_collected_var(self.setvars, var, fd, linenb)
|
||||
# not_added=False
|
||||
# if self.defvars.has_key(var):
|
||||
# self._add_collected_var(self.defvars, var, fd, linenb)
|
||||
# not_added=False
|
||||
# #test les builtsin seulement si variable
|
||||
# if not_added == True and unicode(var, 'utf-8') in builts:
|
||||
# #self.builtsvar.append(var)
|
||||
# return
|
||||
# if not_added == True:
|
||||
# self._add_collected_var(dvar, var, fd, linenb)
|
||||
#
|
||||
# def _collect_vars_in(self, expr, dvar, fd, linenb, tvarstarttoken,
|
||||
# exists=False):
|
||||
# if self.unknown_client == None:
|
||||
# self.unknown_client = []
|
||||
# varcreole = re.compile(tvarstarttoken+'([a-zA-Z0-9_\.{}]+)')
|
||||
# varcreole2 = re.compile(tvarstarttoken+'(\w+)')
|
||||
# varcreolebr = re.compile(tvarstarttoken+'{(\w+)}')
|
||||
# varmulti = re.compile('(\w+)\.(\w+)')
|
||||
# for var in varcreole.findall(expr):
|
||||
# ret = varmulti.match(var)
|
||||
# if ret != None:
|
||||
# if ret.group(1) == cmd_client[0]:
|
||||
# if ret.group(2) not in cmd_client[1]:
|
||||
# self.unknown_client.append(TmplVar(name=ret.group(2), fd=fd, line=linenb))
|
||||
# else:
|
||||
# #%%var.sousvar
|
||||
# self._collect_var_in(dvar, ret.group(1), fd, linenb, exists)
|
||||
# self._collect_var_in(dvar, ret.group(2), fd, linenb, exists)
|
||||
# else:
|
||||
# #%%var
|
||||
# for var2 in varcreole2.findall(tvarstarttoken+var):
|
||||
# self._collect_var_in(dvar, var2, fd, linenb, exists)
|
||||
# #%%{var}
|
||||
# for var2 in varcreolebr.findall(tvarstarttoken+var):
|
||||
# self._collect_var_in(dvar, var2, fd, linenb, exists)
|
||||
#
|
||||
# def _collect_vars(self, tvars, tpattern, all_char=False, with_var=False, with_vars=True, broken=None):
|
||||
# """
|
||||
# collect vars in template for a specified pattern
|
||||
#
|
||||
# :tvars: all collected var are store in this variable
|
||||
# :tpattern: re pattern
|
||||
# :broken: if set, store broken variable
|
||||
# """
|
||||
# if tvars == None:
|
||||
# tvars = {}
|
||||
# tstarttoken = ''
|
||||
# tvarstarttoken = ''
|
||||
# for tmplfd in self._list_tmpl_files():
|
||||
# fh = open(tmplfd, 'r')
|
||||
# lines = fh.readlines()
|
||||
# length = len(lines)
|
||||
# settings = False
|
||||
# if tstarttoken != starttoken or \
|
||||
# tvarstarttoken != varstarttoken:
|
||||
# if all_char:
|
||||
# char = '(.*)'
|
||||
# else:
|
||||
# char = '( *)'
|
||||
# pattern = re.compile(char+starttoken+tpattern)
|
||||
# tstarttoken = starttoken
|
||||
# tvarstarttoken = varstarttoken
|
||||
# for linenb in range(length):
|
||||
# line = lines[linenb]
|
||||
# if line.strip() == '%compiler-settings':
|
||||
# settings = True
|
||||
# if settings and line.strip() == \
|
||||
# '%end compiler-settings'.strip():
|
||||
# settings = False
|
||||
# if not settings:
|
||||
# ret = pattern.match(line.strip())
|
||||
# if ret != None:
|
||||
# expr = ret.group(2).strip()
|
||||
# if with_var:
|
||||
# self._collect_var_in(tvars, expr, tmplfd, linenb)
|
||||
# if with_vars:
|
||||
# self._collect_vars_in(expr,
|
||||
# tvars, tmplfd, linenb,
|
||||
# tvarstarttoken)
|
||||
# len_token = len(varstarttoken)
|
||||
# if broken is not None and expr.strip()[:len_token] != tvarstarttoken:
|
||||
# broken.append(TmplVar(
|
||||
# name=line.strip(),
|
||||
# fd=tmplfd, line=linenb))
|
||||
# else:
|
||||
# tline = line.split('=')
|
||||
# tkey = tline[0].strip()
|
||||
# if tkey == 'cheetahVarStartToken':
|
||||
# tvarstarttoken = tline[1].strip()
|
||||
# elif tkey == 'directiveStartToken':
|
||||
# tstarttoken = tline[1].strip()
|
||||
# pattern = re.compile(tstarttoken+tpattern)
|
||||
# fh.close()
|
||||
# return tvars
|
||||
#
|
||||
# def _collect_for_vars(self):
|
||||
# """
|
||||
# collect all vars generate in 'for'
|
||||
# """
|
||||
# self.brokenfor = []
|
||||
# self.forvars = self._collect_vars(self.forvars, 'for (.+) in (.*)', broken=self.brokenfor)
|
||||
#
|
||||
# def _collect_def_vars(self):
|
||||
# """
|
||||
# collect all vars generate in 'def'
|
||||
# """
|
||||
# self.defvars = self._collect_vars(self.defvars, 'def (.*)\((.*)\)', with_var=True)
|
||||
#
|
||||
# def _collect_set_vars(self):
|
||||
# """
|
||||
# collect all vars generate in 'set'
|
||||
# """
|
||||
# self.setvars = self._collect_vars(self.setvars, 'set (.*)=.*')
|
||||
#
|
||||
# def _collect_define_vars(self):
|
||||
# """
|
||||
# collect all vars generate in 'def'
|
||||
# """
|
||||
# self.var_with_is_defined = self._collect_vars(
|
||||
# self.var_with_is_defined,
|
||||
# "is_defined\(\'(\w+)\'\)",
|
||||
# all_char=True,
|
||||
# with_var=True, with_vars=False)
|
||||
# ##FIXME pas de support de cheetahVarStartToken, ...
|
||||
# #if self.var_with_is_defined == None:
|
||||
# # self.var_with_is_defined = {}
|
||||
# # pattern = re.compile('(.*) %sis_defined\(\'(\w+)\'\)'%varstarttoken)
|
||||
# # for tmplfd in self._list_tmpl_files():
|
||||
# # fh = open(tmplfd, 'r')
|
||||
# # lines = fh.readlines()
|
||||
# # length = len(lines)
|
||||
# # for linenb in range(length):
|
||||
# # line = lines[linenb]
|
||||
# # ret = pattern.match(line)
|
||||
# # if ret != None:
|
||||
# # self._collect_var_in(self.var_with_is_defined, ret.group(2), tmplfd, linenb)
|
||||
# # fh.close()
|
||||
#
|
||||
# def _collect_vars_in_tmplfiles(self):
|
||||
# if self.eoledirs == None or self.tmpl_dir_or_file == None:
|
||||
# raise Exception('Utiliser la methode set_config avant')
|
||||
# # XXX ".eolvars" is a good placeholder for var names to be kept in touch
|
||||
# if self.tmplvars == None:
|
||||
# self.tmplvars = {}
|
||||
# for tmplfd in self._list_tmpl_files():
|
||||
# fh = open(tmplfd, 'r')
|
||||
# lines = fh.readlines()
|
||||
# length = len(lines)
|
||||
# settings = False
|
||||
# tvarstarttoken = varstarttoken
|
||||
# for linenb in range(length):
|
||||
# line = lines[linenb]
|
||||
# if line.strip() == '%compiler-settings':
|
||||
# settings = True
|
||||
# if settings and line.strip() == \
|
||||
# '%end compiler-settings'.strip():
|
||||
# settings = False
|
||||
# if not settings:
|
||||
# self._collect_vars_in(line, self.tmplvars, tmplfd,
|
||||
# linenb, tvarstarttoken, True)
|
||||
# else:
|
||||
# tline = line.split('=')
|
||||
# tkey = tline[0].strip()
|
||||
# if tkey == 'cheetahVarStartToken':
|
||||
# tvarstarttoken = tline[1].strip()
|
||||
#
|
||||
# fh.close()
|
||||
#
|
||||
# storage for the instance reference
|
||||
__instance = None
|
||||
|
||||
def __init__(self):
|
||||
""" Create singleton instance """
|
||||
# Check whether we already have an instance
|
||||
|
||||
if CreoleLinter.__instance is None:
|
||||
# Create and remember instance
|
||||
CreoleLinter.__instance = CreoleLinter.__impl()
|
||||
self.tmpl_dir_or_file = None
|
||||
self.eoledirs = None
|
||||
self.config = None
|
||||
self.variables = {}
|
||||
self.families = []
|
||||
self.tmplvars = None
|
||||
self.forvars = None
|
||||
self.defvars = None
|
||||
self.setvars = None
|
||||
self.unknown_client = None
|
||||
self.brokenfor = None
|
||||
self.var_with_is_defined = None
|
||||
self.exclude_var = None
|
||||
self.skip_var = {}
|
||||
self.conflevel = 'eole'
|
||||
|
||||
# Store instance reference as the only member in the handle
|
||||
self.__dict__['_CreoleLinter__instance'] = CreoleLinter.__instance
|
||||
|
||||
def __getattr__(self, attr):
|
||||
""" Delegate access to implementation """
|
||||
return getattr(self.__instance, attr)
|
||||
|
||||
def __setattr__(self, attr, value):
|
||||
""" Delegate access to implementation """
|
||||
return setattr(self.__instance, attr, value)
|
||||
|
||||
#class SaveItem(CreoleLinter):
|
||||
# """
|
||||
# eolvars not present in the dicos
|
||||
# """
|
||||
# name = 'save'
|
||||
# warnno = 1
|
||||
# warncomment = "Ne pas utiliser la fonction SaveItem comme un test"
|
||||
#
|
||||
# def process(self):
|
||||
# self.load_dics()
|
||||
# if self.pkgname == None:
|
||||
# raise Exception('fichier creolelint.conf incomplet (name)')
|
||||
# filename = join(expanduser('~/.creolelint'), self.pkgname+'.conf')
|
||||
# fh = open(filename, 'w')
|
||||
# fh.write('vardico = '+str(self.get_dicos_name())+'\n')
|
||||
# fh.close()
|
||||
# print('fichier sauvegardé')
|
||||
#
|
||||
# def check(self):
|
||||
# return []
|
||||
#
|
||||
#class OrphansInDicosItem(CreoleLinter):
|
||||
# """
|
||||
# eolvars not present in the dicos
|
||||
# """
|
||||
# name = 'orphans_in_dicos'
|
||||
# warnno = 8
|
||||
# warncomment = "Variable dictionnaire non utilisée dans un template"
|
||||
#
|
||||
# def check(self):
|
||||
# self.load_dics()
|
||||
# self.load_tmpls()
|
||||
#
|
||||
# vars_name = set(self.get_dicos_name())
|
||||
# tmplvars_name = set(self.get_tmplvars_name())
|
||||
# only_in_dicos = vars_name - tmplvars_name
|
||||
# ret = []
|
||||
# skip_var = self.skip_var.get(self.name, {})
|
||||
# for var in only_in_dicos:
|
||||
# if skip_var.has_key(var):
|
||||
# continue
|
||||
# test_start = False
|
||||
# for start in DICO_TEST_VARS:
|
||||
# if var.startswith(start):
|
||||
# test_start = True
|
||||
# break
|
||||
# if not test_start:
|
||||
# ret.append(self.variables[var])
|
||||
# return ret
|
||||
#
|
||||
#class OrphansInTmplItem(CreoleLinter):
|
||||
# """
|
||||
# eolvars not present in the templates
|
||||
# """
|
||||
# name = 'orphans_in_tmpl'
|
||||
# warnno = 8
|
||||
# warncomment = "Variable template non présente dans le dictionnaire"
|
||||
#
|
||||
# def check(self):
|
||||
# self.load_dics()
|
||||
# self.load_tmpls()
|
||||
#
|
||||
# vars_name = self.get_dicos_name()
|
||||
# if self.exclude_var != None:
|
||||
# vars_name.extend(self.exclude_var)
|
||||
# vars_name=set(vars_name)
|
||||
# tmplvars_name = set(self.get_tmplvars_name())
|
||||
# only_in_tmpl = tmplvars_name - vars_name
|
||||
# #remove is_defined
|
||||
# is_defined_name = set(self.var_with_is_defined.keys())
|
||||
# only_in_tmpl = only_in_tmpl - is_defined_name
|
||||
# set_var = set(self.get_setvars_name())
|
||||
# only_in_tmpl = only_in_tmpl - set_var
|
||||
# ret = []
|
||||
# for var in only_in_tmpl:
|
||||
# skipped_location = []
|
||||
# for location in self.tmplvars[var].location:
|
||||
# if self.skip_var.has_key(self.name) and self.skip_var[self.name].has_key(var):
|
||||
# if not location in self.skip_var[self.name][var]:
|
||||
# skipped_location.append(location)
|
||||
# else:
|
||||
# skipped_location.append(location)
|
||||
# if skipped_location != []:
|
||||
# tmplvar = TmplVar(var, '', 0)
|
||||
# tmplvar.set_location(skipped_location)
|
||||
# ret.append(tmplvar)
|
||||
# #results.append(self.tmplvars[var])
|
||||
# return ret
|
||||
#
|
||||
#class OrphansDefItem(CreoleLinter):
|
||||
# name = 'orphans_def'
|
||||
# warnno = 7
|
||||
# warncomment = "Fonction définie mais non utilisée"
|
||||
#
|
||||
# def check(self):
|
||||
# self.load_tmpls()
|
||||
# results = []
|
||||
# for defvar in self.get_defvars_name():
|
||||
# defname = {}
|
||||
# for filedesc, linenb in self.defvars[defvar].location:
|
||||
# if not defname.has_key((defvar, filedesc)):
|
||||
# defname[(defvar, filedesc)]=linenb
|
||||
# else:
|
||||
# defname[(defvar, filedesc)]="exists"
|
||||
# for defvar, filedesc in defname.keys():
|
||||
# if defname[(defvar, filedesc)] != "exists":
|
||||
# results.append(TmplVar(name=defvar, fd=filedesc, line=defname[(defvar, filedesc)]))
|
||||
#
|
||||
# return results
|
||||
#
|
||||
#class OrphansSetItem(CreoleLinter):
|
||||
# name = 'orphans_set'
|
||||
# warnno = 7
|
||||
# warncomment = "Variable définie dans le template mais non utilisée"
|
||||
#
|
||||
# def check(self):
|
||||
# self.load_tmpls()
|
||||
# results = []
|
||||
# tmpl_vars = set(self.get_tmplvars_name())
|
||||
# for setvar in self.get_setvars_name():
|
||||
# setname = {}
|
||||
# for filedesc, linenb in self.setvars[setvar].location:
|
||||
# if setname.has_key((setvar, filedesc)) == False:
|
||||
# setname[(setvar, filedesc)]=linenb
|
||||
# else:
|
||||
# setname[(setvar, filedesc)]="exists"
|
||||
#
|
||||
# for setvar, filedesc in setname.keys():
|
||||
# if setname[(setvar, filedesc)] != "exists":
|
||||
# results.append(TmplVar(name=setvar, fd=filedesc, line=setname[(setvar, filedesc)]))
|
||||
#
|
||||
# return results
|
||||
#
|
||||
#class OrphansForItem(CreoleLinter):
|
||||
# name = 'orphans_for'
|
||||
# warnno = 7
|
||||
# warncomment = "Variable définie dans une boucle mais non utilisée"
|
||||
#
|
||||
# def check(self):
|
||||
# self.load_tmpls()
|
||||
# results = []
|
||||
# for forvar in self.get_forvars_name():
|
||||
# forname = {}
|
||||
# for filedesc, linenb in self.forvars[forvar].location:
|
||||
# if forname.has_key((forvar, filedesc)) == False:
|
||||
# forname[(forvar, filedesc)]=linenb
|
||||
# else:
|
||||
# forname[(forvar, filedesc)]="exists"
|
||||
#
|
||||
# for forvar, filedesc in forname.keys():
|
||||
# if forname[(forvar, filedesc)] != "exists":
|
||||
# results.append(TmplVar(name=forvar, fd=filedesc, line=forname[(forvar, filedesc)]))
|
||||
# return results
|
||||
#
|
||||
#class OrphansDicosFilesItem(CreoleLinter):
|
||||
# """
|
||||
# """
|
||||
# name = 'orphans_dicos_files'
|
||||
# warnno = 1
|
||||
# warncomment = "Template déclaré dans le dicos inexistant"
|
||||
#
|
||||
# def check(self):
|
||||
# self.load_dics()
|
||||
#
|
||||
# dicos_files = []
|
||||
# for filen in self.get_dicos_files():
|
||||
# dicos_files.append(basename(filen))
|
||||
# dicos_files = set(dicos_files)
|
||||
# tmpl_files = []
|
||||
# for filen in self._list_tmpl_files():
|
||||
# tmpl_files.append(unicode(basename(filen), 'utf-8'))
|
||||
# tmpl_files=set(tmpl_files)
|
||||
# orphans = dicos_files - tmpl_files
|
||||
# ret = []
|
||||
# for var in orphans:
|
||||
# if self.skip_var.has_key(self.name) and not self.skip_var[self.name].has_key(var):
|
||||
# ret.append(var)
|
||||
# else:
|
||||
# ret.append(var)
|
||||
#
|
||||
# return ret
|
||||
#
|
||||
#class OrphansTmplFilesItem(CreoleLinter):
|
||||
# """
|
||||
# """
|
||||
# name = 'orphans_tmpl_files'
|
||||
# warnno = 1
|
||||
# warncomment = "Template non déclaré dans le dicos"
|
||||
#
|
||||
# def check(self):
|
||||
# self.load_dics()
|
||||
#
|
||||
# dicos_files = []
|
||||
# for filen in self.get_dicos_files():
|
||||
# dicos_files.append(basename(filen))
|
||||
# dicos_files = set(dicos_files)
|
||||
# tmpl_files = []
|
||||
# for filen in self._list_tmpl_files():
|
||||
# tmpl_files.append(unicode(basename(filen), 'utf-8'))
|
||||
# tmpl_files=set(tmpl_files)
|
||||
# return tmpl_files - dicos_files
|
||||
#
|
||||
class WrongDicosNameItem(CreoleLinter):
|
||||
name = 'wrong_dicos_name'
|
||||
warnno = 6
|
||||
warncomment = "Dictionnaire avec un nom invalide"
|
||||
|
||||
def check(self):
|
||||
if self.conflevel == 'common':
|
||||
pattern = '(0'
|
||||
elif self.conflevel == 'conf':
|
||||
pattern = '(1'
|
||||
elif self.conflevel == 'eole':
|
||||
pattern = '(2'
|
||||
else:
|
||||
pattern = '([3-9]'
|
||||
pattern += '[0-9]_[a-z0-9_]+)'
|
||||
cpattern = re.compile(pattern)
|
||||
ret = []
|
||||
for filename in self.get_dico_file_names():
|
||||
name = basename(filename)
|
||||
if cpattern.match(name) == None:
|
||||
ret.append(name)
|
||||
return ret
|
||||
|
||||
class HiddenIfInDicosItem(CreoleLinter):
|
||||
name = 'hidden_if_in_dicos'
|
||||
warnno = 5
|
||||
warncomment = "Dictionnaire contenant un hidden_if_*"
|
||||
|
||||
def check(self):
|
||||
ret = []
|
||||
dtd = parse_dtd(self.get_dtd())
|
||||
for filename in self.get_dico_file_names():
|
||||
if filename in OLD_DICOS:
|
||||
continue
|
||||
parse = parse_xml_file(filename, dtd, parse_all=False)
|
||||
for cond in parse['conditions'].values():
|
||||
if cond[0]['name'].startswith('hidden_if_'):
|
||||
ret.append(filename)
|
||||
break
|
||||
return ret
|
||||
|
||||
class ConditionWithoutTarget(CreoleLinter):
|
||||
name = 'condition_without_target'
|
||||
warnno = 5
|
||||
warncomment = "Dictionnaire contenant une condition sans target"
|
||||
|
||||
def check(self):
|
||||
ret = []
|
||||
|
||||
dtd = parse_dtd(self.get_dtd())
|
||||
for filename in self.get_dico_file_names():
|
||||
if filename in OLD_DICOS:
|
||||
continue
|
||||
parse = parse_xml_file(filename, dtd, parse_all=False)
|
||||
for cond in parse['conditions'].values():
|
||||
for con in cond:
|
||||
if con['family'] == con['list'] == con['variable'] == []:
|
||||
ret.append(filename)
|
||||
break
|
||||
return ret
|
||||
|
||||
class ObligatoireInDicosItem(CreoleLinter):
|
||||
name = 'obligatoire_in_dicos'
|
||||
warnno = 5
|
||||
warncomment = "Dictionnaire contenant un check \"obligatoire\""
|
||||
|
||||
def check(self):
|
||||
ret = []
|
||||
dtd = parse_dtd(self.get_dtd())
|
||||
for filename in self.get_dico_file_names():
|
||||
if filename in OLD_DICOS:
|
||||
continue
|
||||
parse = parse_xml_file(filename, dtd, parse_all=False)
|
||||
for cond in parse['checks'].values():
|
||||
if cond[0][0] == 'obligatoire':
|
||||
ret.append(filename)
|
||||
break
|
||||
return ret
|
||||
|
||||
|
||||
class FamilyWithoutHelp(CreoleLinter):
|
||||
name = 'family_without_help'
|
||||
warnno = 5
|
||||
warncomment = "Famille sans balise d'aide"
|
||||
|
||||
def check(self):
|
||||
self.load_dics()
|
||||
ret = []
|
||||
for grp in self.config.creole.iter_groups():
|
||||
doc = grp[1].cfgimpl_get_description().impl_get_information('help', None)
|
||||
if doc is None:
|
||||
ret.append(grp[0])
|
||||
return ret
|
||||
|
||||
class FamilyWithoutIcon(CreoleLinter):
|
||||
name = 'family_without_icon'
|
||||
warnno = 5
|
||||
warncomment = "Famille sans icône spécifique"
|
||||
|
||||
def check(self):
|
||||
self.load_dics()
|
||||
ret = []
|
||||
for grp in self.config.creole.iter_groups():
|
||||
if grp[1].cfgimpl_get_description().impl_get_information('icon') is None:
|
||||
ret.append(grp[0])
|
||||
return ret
|
||||
|
||||
#class DefineItem(CreoleLinter):
|
||||
# """
|
||||
# check for syntaxes
|
||||
# """
|
||||
# name = 'define'
|
||||
# warnno = 4
|
||||
# warncomment = "Redéfinition d'un variable d'un dictionnaire"
|
||||
#
|
||||
# def check(self):
|
||||
# """
|
||||
# verifie si une variable définie est une variable du dictionnaire
|
||||
# """
|
||||
# self.load_dics()
|
||||
# self.load_tmpls()
|
||||
# dicos = set(self.get_dicos_name())
|
||||
# defv = set(self.get_defvars_name())
|
||||
# ret=[]
|
||||
# for var in defv & dicos:
|
||||
# ret.append(self.defvars[var])
|
||||
# return ret
|
||||
#
|
||||
class BuiltinsItem(CreoleLinter):
|
||||
"""
|
||||
verifier si une variable de dico n'est pas dans l'espace de nommage
|
||||
"""
|
||||
name = 'builtins'
|
||||
warnno = 4
|
||||
warncomment = "Variable identitique à une fonction python"
|
||||
|
||||
def check(self):
|
||||
self.load_dics()
|
||||
# self.load_tmpls()
|
||||
ret = []
|
||||
#dans le dictionnaire
|
||||
for var in set(builts) & set(self.get_dicos_name()):
|
||||
ret.append(self.variables[var])
|
||||
# #dans les variables de template
|
||||
# for var in set(builts) & set(self.get_tmplvars_name()):
|
||||
# ret.append(self.tmplvars[var])
|
||||
# #dans les boucles for
|
||||
# for var in set(builts) & set(self.get_forvars_name()):
|
||||
# ret.append(self.forvars[var])
|
||||
# #dans la definition de variable dans un template
|
||||
# for var in set(builts) & set(self.get_setvars_name()):
|
||||
# ret.append(self.setvars[var])
|
||||
# #dans les noms de fonction
|
||||
# for var in set(builts) & set(self.get_defvars_name()):
|
||||
# ret.append(self.defvars[var])
|
||||
return ret
|
||||
|
||||
#class SyntaxForItem(CreoleLinter):
|
||||
# """
|
||||
# verifie la syntaxe de la ligne for
|
||||
# """
|
||||
# name = 'syntax_for'
|
||||
# warnno = 1
|
||||
# warncomment = "Syntaxe de la ligne for incorrect"
|
||||
# def check(self):
|
||||
# self.load_tmpls()
|
||||
# return self.brokenfor
|
||||
#
|
||||
#class SyntaxVarItem(CreoleLinter):
|
||||
# """
|
||||
# verifie les variables suivant la syntaxe de pattern
|
||||
# """
|
||||
# name = 'syntax_var'
|
||||
# pattern = '([a-z0-9][a-z0-9]+_[a-z0-9_]+)'
|
||||
# warnno = 6
|
||||
# warncomment = "La variable ne respecte pas la regexp %s" % pattern
|
||||
#
|
||||
# def check(self):
|
||||
# cpattern = re.compile(self.pattern)
|
||||
# self.load_dics()
|
||||
# self.load_tmpls()
|
||||
# ret=[]
|
||||
# #dans le dictionnaire
|
||||
# for var in self.get_dicos_name():
|
||||
# if cpattern.match(var) == None:
|
||||
# ret.append(self.variables[var])
|
||||
# #dans les variables de template
|
||||
# for var in self.get_tmplvars_name():
|
||||
# if cpattern.match(var) == None:
|
||||
# skipped_location = []
|
||||
# for location in self.tmplvars[var].location:
|
||||
# if self.skip_var.has_key(self.name) and self.skip_var[self.name].has_key(var):
|
||||
# if not location in self.skip_var[self.name][var]:
|
||||
# skipped_location.append(location)
|
||||
# else:
|
||||
# skipped_location.append(location)
|
||||
# if skipped_location != []:
|
||||
# tmplvar = TmplVar(var, '', 0)
|
||||
# tmplvar.set_location(skipped_location)
|
||||
# ret.append(tmplvar)
|
||||
# #ret.append(self.tmplvars[var])
|
||||
# #dans les boucles for
|
||||
# for var in self.get_forvars_name():
|
||||
# if cpattern.match(var) == None:
|
||||
# ret.append(self.forvars[var])
|
||||
# #dans la definition de variable dans un template
|
||||
# for var in self.get_setvars_name():
|
||||
# if cpattern.match(var) == None:
|
||||
# ret.append(self.setvars[var])
|
||||
# return ret
|
||||
#
|
||||
#class ForbiddenTemplateVarItem(CreoleLinter):
|
||||
# """
|
||||
# vérifie la présence des noms de variable interdits dans les templates
|
||||
# """
|
||||
# name = 'syntax_var2'
|
||||
# warnno = 6
|
||||
# warncomment = "Nom de variable interdit dans un template"
|
||||
#
|
||||
# def check(self):
|
||||
# #self.load_dics()
|
||||
# self.load_tmpls()
|
||||
# ret=[]
|
||||
# #dans les variables de template
|
||||
# for var in self.get_tmplvars_name():
|
||||
# for start in DICO_TEST_VARS:
|
||||
# if var.startswith(start):
|
||||
# ret.append(var)
|
||||
# break
|
||||
# return ret
|
||||
#
|
||||
#class SyntaxFunctionItem(CreoleLinter):
|
||||
# """
|
||||
# verifie les fonctions suivant la syntaxe de pattern
|
||||
# """
|
||||
# name = 'syntax_function'
|
||||
# pattern = '([a-z0-9][a-z0-9]+_[a-z0-9_]+)'
|
||||
# warnno = 6
|
||||
# warncomment = "La fonction ne respecte pas la regexp %s" % pattern
|
||||
#
|
||||
# def check(self):
|
||||
# cpattern = re.compile(self.pattern)
|
||||
# self.load_tmpls()
|
||||
# ret=[]
|
||||
# #dans les noms de fonction
|
||||
# for var in self.get_defvars_name():
|
||||
# if cpattern.match(var) == None:
|
||||
# ret.append(self.defvars[var])
|
||||
# return ret
|
||||
#
|
||||
#class OrphansVarHelpItem(CreoleLinter):
|
||||
# name = 'orphans_var_help'
|
||||
# warnno = 3
|
||||
# warncomment = "Aide définie dans le dictionnaire pour une variable inexistante"
|
||||
#
|
||||
# def check(self):
|
||||
# self.load_dics()
|
||||
# vars_name = set(self.get_dicos_name())
|
||||
# vars_help = set(self.creoledic.get_helps()['variables'].keys())
|
||||
# #print vars_help
|
||||
# only_in_help = vars_help - vars_name
|
||||
# results = []
|
||||
# for tmpl in only_in_help:
|
||||
# results.append(tmpl)
|
||||
# return results
|
||||
|
||||
#class OrphansFamHelpItem(CreoleLinter):
|
||||
# name = 'orphans_fam_help'
|
||||
# warnno = 3
|
||||
# warncomment = "Aide définie dans le dictionnaire pour une famille inexistante"
|
||||
#
|
||||
# def check(self):
|
||||
# self.load_dics()
|
||||
# #FIXME
|
||||
# vars_name = set(self.families)
|
||||
# vars_help = set(self.creoledic.get_helps()['families'].keys())
|
||||
# only_in_help = vars_help - vars_name
|
||||
# results = []
|
||||
# for tmpl in only_in_help:
|
||||
# results.append(tmpl)
|
||||
# return results
|
||||
#
|
||||
class ValidVarLabelItem(CreoleLinter):
|
||||
name = 'valid_var_label'
|
||||
warnno = 5
|
||||
warncomment = "Libellé de variable non valide dans un dictionnaire"
|
||||
|
||||
def check(self):
|
||||
self.load_dics()
|
||||
ret = []
|
||||
for var in self.variables.values():
|
||||
if not is_container_var(var.name):
|
||||
ret.extend(is_correct(var.description, var.name))
|
||||
return ret
|
||||
|
||||
class ActivationVarWithoutHelp(CreoleLinter):
|
||||
name = 'activation_var_without_help'
|
||||
warnno = 5
|
||||
warncomment = "Variable d'activation sans balise d'aide"
|
||||
|
||||
def check(self):
|
||||
self.load_dics()
|
||||
ret = []
|
||||
for var, var_obj in self.variables.items():
|
||||
if var.startswith('activer_') and var not in EXCLUDE_ACTIVATION_VARS:
|
||||
if var_obj.help is None:
|
||||
ret.append(var)
|
||||
return ret
|
||||
|
||||
class ValidSeparatorLabelItem(CreoleLinter):
|
||||
name = 'valid_separator_label'
|
||||
warnno = 5
|
||||
warncomment = "Libellé de séparateur non valide dans un dictionnaire"
|
||||
|
||||
def check(self):
|
||||
self.load_dics()
|
||||
ret = []
|
||||
|
||||
for var, var_obj in self.variables.items():
|
||||
if var_obj.separator == '':
|
||||
#FIXME: variables de conteneur dynamiques
|
||||
continue
|
||||
ret.extend(is_correct(var_obj.separator[0], var))
|
||||
return ret
|
||||
|
||||
class ValidHelpLabelItem(CreoleLinter):
|
||||
name = 'valid_help_label'
|
||||
warnno = 5
|
||||
warncomment = "Libellé d'aide non valide dans un dictionnaire"
|
||||
|
||||
def check(self):
|
||||
self.load_dics()
|
||||
ret = []
|
||||
for var, var_obj in self.variables.items():
|
||||
# help/variable
|
||||
ret.extend(is_correct(var_obj.help, var))
|
||||
for grp in self.config.creole.iter_groups():
|
||||
# help/family
|
||||
ret.extend(is_correct(grp[1].cfgimpl_get_description().impl_get_information('help', ''),
|
||||
grp[0], family=True))
|
||||
return ret
|
||||
|
||||
class ValidSlaveValue(CreoleLinter):
|
||||
name = 'valid_slave_value'
|
||||
warnno = 5
|
||||
warncomment = "Variable esclave avec une liste en valeur défaut"
|
||||
|
||||
def check(self):
|
||||
self.load_dics()
|
||||
ret = []
|
||||
for var, var_obj in self.variables.items():
|
||||
if var_obj.is_slave:
|
||||
if len(var_obj.defaultvalue) > 1:
|
||||
ret.append(var)
|
||||
return ret
|
||||
|
||||
##class ValidCheckEnumOuiNon(CreoleLinter):
|
||||
## name = 'valid_check_enum_ouinon'
|
||||
## warnno = 6
|
||||
## warncomment = "Variable avec un valid_enum à oui/non au lieu du type oui/non"
|
||||
##
|
||||
## def check(self):
|
||||
## ret = []
|
||||
## for var, content in self.creoledic.variables.items():
|
||||
## print content
|
||||
## if str(type(content)) != "<class 'creole.typeole.OuiNon'>":
|
||||
## for check in content.choices:
|
||||
## if check[0] == u'valid_enum':
|
||||
## for valid_enum in check[1]:
|
||||
## if valid_enum['value'].startswith('['):
|
||||
## eval_valid_enum = eval(valid_enum['value'])
|
||||
## if set(eval_valid_enum) == set(['non', 'oui']):
|
||||
## ret.append(var)
|
||||
## return ret
|
||||
#
|
||||
##class ValidCheckEnumOnOff(CreoleLinter):
|
||||
## name = 'valid_check_enum_onoff'
|
||||
## warnno = 6
|
||||
## warncomment = "Variable avec un valid_enum à on/off au lieu du type on/off"
|
||||
##
|
||||
## def check(self):
|
||||
## ret = []
|
||||
## for var, content in self.creoledic.variables.items():
|
||||
## if str(type(content)) != "<class 'creole.typeole.OnOff'>":
|
||||
## for check in content.checks:
|
||||
## if check[0] == u'valid_enum':
|
||||
## for valid_enum in check[1]:
|
||||
## if valid_enum['value'].startswith('['):
|
||||
## eval_valid_enum = eval(valid_enum['value'])
|
||||
## if set(eval_valid_enum) == set(['on', 'off']):
|
||||
## ret.append(var)
|
||||
## return ret
|
||||
#
|
||||
class TabsInDicosItem(CreoleLinter):
|
||||
name = 'tabs_in_dicos'
|
||||
warnno = 5
|
||||
warncomment = "Tabulation dans le dictionnaire au lieu de 4 espaces"
|
||||
|
||||
def check(self):
|
||||
return self._parse_tabs_in_dicos()
|
||||
|
||||
#class ValidClientOption(CreoleLinter):
|
||||
# name = 'valid_client_option'
|
||||
# warnno = 6
|
||||
# warncomment = "Option inconnu pour %s" % cmd_client[0]
|
||||
#
|
||||
# def check(self):
|
||||
# self.load_tmpls()
|
||||
# return self.unknown_client
|
||||
|
||||
class ValidParseTmpl(CreoleLinter):
|
||||
name = 'valid_parse_tmpl'
|
||||
warnno = 1
|
||||
warncomment = "Template Non valide"
|
||||
display = False
|
||||
|
||||
def check(self):
|
||||
parse_templates(self._list_tmpl_files())
|
||||
return []
|
||||
|
||||
|
||||
class ValidDTDItem(CreoleLinter):
|
||||
name = 'valid_dtd'
|
||||
warnno = 1
|
||||
warncomment = "DTD Non valide"
|
||||
display = False
|
||||
|
||||
def check(self):
|
||||
dtd = self.get_dtd()
|
||||
for filename in self.get_dico_file_names():
|
||||
system_code(['xmllint', '--noout', '--dtdvalid', dtd, filename])
|
||||
return []
|
||||
|
||||
class OldFwFile(CreoleLinter):
|
||||
name = 'old_fw_file'
|
||||
warnno = 5
|
||||
warncomment = "Ancien fichier eole-firewall présent sur le serveur"
|
||||
|
||||
def check(self):
|
||||
fw_templates = '/usr/share/eole/creole/distrib/*.fw'
|
||||
fw_files = '/usr/share/eole/firewall/*.fw'
|
||||
return glob(fw_files) + glob(fw_templates)
|
||||
|
||||
def validate(keyword, ansi, tmpl):
|
||||
globs = globals()
|
||||
classitem = None
|
||||
for cls in globs:
|
||||
if cls.startswith('_') and type(globs[cls])!=types.ClassType and cls == 'CreoleLinter' and cls == 'TmplVar':
|
||||
continue
|
||||
if hasattr(globs[cls], 'name'):
|
||||
if globs[cls].name == keyword:
|
||||
classitem = globs[cls]
|
||||
break
|
||||
if classitem == None:
|
||||
raise Exception('test %s inconnu'%keyword)
|
||||
cl = classitem()
|
||||
if cl.eoledirs == None:
|
||||
cl.set_config(tmpl_dir_or_file=tmpl)
|
||||
ansi.process(cl)
|
||||
|
@ -1,132 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
modules = [
|
||||
'Zéphir',
|
||||
'Eolebase',
|
||||
'Amon',
|
||||
'Sentinelle',
|
||||
'Sphynx',
|
||||
'Scribe',
|
||||
'Eclair',
|
||||
'Horus',
|
||||
'ZéphirLog',
|
||||
'PreludeManager',
|
||||
'AmonEcole',
|
||||
'EoleVZ',
|
||||
'Seshat',
|
||||
'ClientScribe',
|
||||
'ClientHorus']
|
||||
|
||||
projets = [
|
||||
' EOLE', # confusion avec eole-annuaire
|
||||
'EAD',
|
||||
'ead-web',
|
||||
'ead-server',
|
||||
'frontend',
|
||||
'backend',
|
||||
'Era',
|
||||
'ESU',
|
||||
'AGRIATES',
|
||||
'RACINE-AGRIATES',
|
||||
'Samba',
|
||||
'Creole',
|
||||
'GenConfig',
|
||||
'EoleDB',
|
||||
'EoleSSO',
|
||||
'Zéphir',
|
||||
"application Zéphir",
|
||||
"Zéphir-web",
|
||||
]
|
||||
|
||||
os_logiciels_protocoles = [
|
||||
'Linux',
|
||||
'GNU/Linux',
|
||||
'Ubuntu',
|
||||
'Unix',
|
||||
'Windows',
|
||||
'Microsoft',
|
||||
# 'ALIAS',
|
||||
'BlockInput',
|
||||
'Epreuve@SSR',
|
||||
'SSH',
|
||||
'OpenSSH',
|
||||
'DHCP',
|
||||
'DHCPd',
|
||||
'ClamAV',
|
||||
'NuFW',
|
||||
'NuWinC',
|
||||
'Nuauth',
|
||||
'DansGuardian',
|
||||
'Bacula',
|
||||
'Bareos',
|
||||
'TCP',
|
||||
'UDP',
|
||||
'ICMP',
|
||||
'IP',
|
||||
' IPsec', # confusion avec la commande ipsec
|
||||
'strongSwan',
|
||||
'DMZ',
|
||||
'FTP',
|
||||
'SMB',
|
||||
'XML',
|
||||
'XML-RPC',
|
||||
' SSO',
|
||||
# 'CAS',
|
||||
'SAML',
|
||||
'Sympa',
|
||||
'MySQL',
|
||||
'SpamAssassin',
|
||||
'web',
|
||||
'phpMyAdmin',
|
||||
'Grr',
|
||||
'Gibii',
|
||||
'Gepi',
|
||||
'SPIP-EVA',
|
||||
'Envole',
|
||||
'Envole 2',
|
||||
'WebShare',
|
||||
' CSS', # confusion avec .css
|
||||
'CUPS',
|
||||
'OpenOffice.org',
|
||||
'GDM',
|
||||
'client léger',
|
||||
'client lourd',
|
||||
'OpenLDAP',
|
||||
'ProFTPD',
|
||||
'Vim',
|
||||
'Controle-vnc',
|
||||
'BE1D',
|
||||
'RVP',
|
||||
'PostgreSQL',
|
||||
'Squid',
|
||||
'NUT',
|
||||
'PPPoE',
|
||||
'VLAN',
|
||||
'SSL',
|
||||
'Nginx',
|
||||
'reverse proxy',
|
||||
'SquirrelMail',
|
||||
'LDAP',
|
||||
'FreeRADIUS',
|
||||
'LightSquid',
|
||||
'SARG',
|
||||
'iptables',
|
||||
'Netfilter',
|
||||
'POSH',
|
||||
'InterBase',
|
||||
'OCS',
|
||||
]
|
||||
|
||||
divers = [
|
||||
'Éducation nationale',
|
||||
'Internet',
|
||||
'intranet',
|
||||
'pare-feu',
|
||||
'anti-virus',
|
||||
'anti-spam',
|
||||
'USB',
|
||||
'relai',
|
||||
]
|
||||
|
||||
entities = modules + projets + os_logiciels_protocoles + divers
|
||||
|
@ -1,82 +0,0 @@
|
||||
"""errno-specific classes"""
|
||||
|
||||
import sys, os, errornb
|
||||
|
||||
class Error(EnvironmentError):
|
||||
def __repr__(self):
|
||||
return "%s.%s %r: %s " %(self.__class__.__module__,
|
||||
self.__class__.__name__,
|
||||
self.__class__.__doc__,
|
||||
" ".join(map(str, self.args)),
|
||||
#repr(self.args)
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
s = "[%s]: %s" %(self.__class__.__doc__,
|
||||
" ".join(map(str, self.args)),
|
||||
)
|
||||
return s
|
||||
|
||||
#FIXME set the different error better suited than errno
|
||||
_winerrnomap = {
|
||||
2: errsymb.ENOENT,
|
||||
3: errsymb.ENOENT,
|
||||
17: errsymb.EEXIST,
|
||||
22: errsymb.ENOTDIR,
|
||||
267: errsymb.ENOTDIR,
|
||||
5: errsymb.EACCES, # anything better?
|
||||
}
|
||||
|
||||
class ErrorMaker(object):
|
||||
""" lazily provides Exception classes for each possible POSIX errno
|
||||
(as defined per the 'errno' module). All such instances
|
||||
subclass EnvironmentError.
|
||||
"""
|
||||
Error = Error
|
||||
_errno2class = {}
|
||||
|
||||
def __getattr__(self, name):
|
||||
eno = getattr(errno, name)
|
||||
cls = self._geterrnoclass(eno)
|
||||
setattr(self, name, cls)
|
||||
return cls
|
||||
|
||||
def _geterrnoclass(self, eno):
|
||||
try:
|
||||
return self._errno2class[eno]
|
||||
except KeyError:
|
||||
clsname = errno.errorcode.get(eno, "UnknownErrno%d" %(eno,))
|
||||
errorcls = type(Error)(clsname, (Error,),
|
||||
{'__module__':'py.error',
|
||||
'__doc__': os.strerror(eno)})
|
||||
self._errno2class[eno] = errorcls
|
||||
return errorcls
|
||||
|
||||
def checked_call(self, func, *args):
|
||||
""" call a function and raise an errno-exception if applicable. """
|
||||
__tracebackhide__ = True
|
||||
try:
|
||||
return func(*args)
|
||||
except self.Error:
|
||||
raise
|
||||
except EnvironmentError:
|
||||
cls, value, tb = sys.exc_info()
|
||||
if not hasattr(value, 'errno'):
|
||||
raise
|
||||
__tracebackhide__ = False
|
||||
errno = value.errno
|
||||
try:
|
||||
if not isinstance(value, WindowsError):
|
||||
raise NameError
|
||||
except NameError:
|
||||
# we are not on Windows, or we got a proper OSError
|
||||
cls = self._geterrnoclass(errno)
|
||||
else:
|
||||
try:
|
||||
cls = self._geterrnoclass(_winerrnomap[errno])
|
||||
except KeyError:
|
||||
raise value
|
||||
raise cls("%s%r" % (func.__name__, args))
|
||||
__tracebackhide__ = True
|
||||
|
||||
error = ErrorMaker()
|
@ -1,76 +0,0 @@
|
||||
# coding: utf-8
|
||||
import re
|
||||
import unicodedata
|
||||
from entities import entities
|
||||
|
||||
# ______________________________________________________________________________
|
||||
|
||||
ENCODING = 'utf-8'
|
||||
|
||||
def strip_accents(string):
|
||||
return unicodedata.normalize('NFKD', unicode(string, ENCODING)
|
||||
).encode('ASCII', 'ignore')
|
||||
|
||||
def normalize_entities():
|
||||
"""
|
||||
enleve les accents de la liste des entites + minuscules
|
||||
:return: entities normalisé
|
||||
"""
|
||||
norm_entities = []
|
||||
for entitie in entities:
|
||||
norm_entitie = strip_accents(entitie).lower()
|
||||
norm_entities.append(norm_entitie)
|
||||
return norm_entities
|
||||
|
||||
NORM_ENTITIES = normalize_entities()
|
||||
|
||||
# ______________________________________________________________________________
|
||||
|
||||
def parse_string(text):
|
||||
"""
|
||||
enlève les accents d'un texte
|
||||
"""
|
||||
# libelle = strip_accents(text)
|
||||
words = re.findall('([a-zA-Zéèàùêôëö_]+)', text)
|
||||
return words
|
||||
|
||||
def is_in_entities(text):
|
||||
"""
|
||||
donne l'index dans entities du texte
|
||||
"""
|
||||
norm_text = text.lower()
|
||||
index = None
|
||||
if norm_text in NORM_ENTITIES:
|
||||
index = NORM_ENTITIES.index(norm_text)
|
||||
return index
|
||||
|
||||
def is_correct(libelle, name, family=False):
|
||||
if libelle is not None and type(libelle) != str:
|
||||
libelle = unicode.encode(libelle, ENCODING)
|
||||
ret = []
|
||||
if libelle == '' or libelle is None:
|
||||
return ret
|
||||
if libelle[0].islower():
|
||||
#FIXME: faux positifs connus
|
||||
if not libelle.startswith('ejabberd') and \
|
||||
not libelle.startswith('phpMyAdmin'):
|
||||
ret.append('%%%%%s : phrase sans majuscule'%name)
|
||||
for text in parse_string(libelle):
|
||||
text_index = is_in_entities(text)
|
||||
if not text_index == None:
|
||||
if str(text) != str(entities[text_index]):
|
||||
#FIXME: faux positifs connus
|
||||
if 'ipsec.conf' in libelle or 'test-rvp' in libelle \
|
||||
or 'bareos-' in libelle \
|
||||
or 'bacula-' in libelle \
|
||||
or '/var/log/zephir' in libelle \
|
||||
or 'exemple : eolebase' in libelle:
|
||||
continue
|
||||
ent = str(unicode.encode((unicode(entities[text_index], ENCODING)), ENCODING))
|
||||
if family:
|
||||
ret.append('famille [%s] : %s => %s' % (str(name), text, ent))
|
||||
else:
|
||||
ret.append('%%%%%s : %s => %s' % (str(name), text, ent))
|
||||
return ret
|
||||
# ______________________________________________________________________________
|
||||
|
@ -1,660 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
from os.path import basename
|
||||
from creole.loader import creole_loader
|
||||
from creole.client import CreoleClient
|
||||
from creole.template import CreoleGet, IsDefined, CreoleTemplateEngine, CreoleMaster
|
||||
from creole import eosfunc
|
||||
from tiramisu.option import *
|
||||
from tiramisu import Config
|
||||
from tiramisu.error import ConfigError, PropertiesOptionError, \
|
||||
RequirementError, ValueWarning
|
||||
from Cheetah import Parser, Compiler
|
||||
from Cheetah.Template import Template
|
||||
from Cheetah.NameMapper import NotFound
|
||||
from pyeole.ansiprint import print_red
|
||||
from creole.eosfunc import valid_regexp
|
||||
from Cheetah.Unspecified import Unspecified
|
||||
import warnings
|
||||
|
||||
|
||||
DEBUG = False
|
||||
#DEBUG = True
|
||||
|
||||
|
||||
client = CreoleClient()
|
||||
compilerSettings = {'directiveStartToken' : u'%',
|
||||
'cheetahVarStartToken' : u'%%', 'EOLSlurpToken' : u'%',
|
||||
'PSPStartToken' : u'µ' * 10, 'PSPEndToken' : u'µ' * 10,
|
||||
'commentStartToken' : u'µ' * 10, 'commentEndToken' : u'µ' * 10,
|
||||
'multiLineCommentStartToken' : u'µ' * 10,
|
||||
'multiLineCommentEndToken' : u'µ' * 10}
|
||||
|
||||
#======================= CHEETAH =======================
|
||||
# This class is used to retrieve all template vars
|
||||
#true_HighLevelParser = Parser._HighLevelParser
|
||||
global cl_chunks, cl_vars
|
||||
cl_chunks = set()
|
||||
cl_vars = set()
|
||||
class cl_Parser(Parser.Parser):
|
||||
|
||||
def getCheetahVarNameChunks(self, *args, **kwargs):
|
||||
global cl_chunks
|
||||
chunks = super(cl_Parser, self).getCheetahVarNameChunks(*args, **kwargs)
|
||||
for chunk in chunks:
|
||||
#if false, it's internal variable
|
||||
if chunk[1]:
|
||||
name = chunk[0]
|
||||
#remove master if master/slave and add force adding master
|
||||
if '.' in name:
|
||||
cl_chunks.add(name.split('.')[-1])
|
||||
cl_chunks.add(name.split('.')[0])
|
||||
else:
|
||||
cl_chunks.add(name)
|
||||
return chunks
|
||||
|
||||
def getCheetahVar(self, *args, **kwargs):
|
||||
global cl_vars
|
||||
var = super(cl_Parser, self).getCheetahVar(*args, **kwargs)
|
||||
if not var.startswith(u'VFFSL('):
|
||||
cl_vars.add(var)
|
||||
return var
|
||||
|
||||
def getVars():
|
||||
global cl_chunks, cl_vars
|
||||
#retrieve all calculated vars
|
||||
ret = list(cl_chunks - cl_vars)
|
||||
cl_chunks = set()
|
||||
cl_vars = set()
|
||||
return ret
|
||||
|
||||
class CompilerGetVars(Compiler.ModuleCompiler):
|
||||
parserClass = cl_Parser
|
||||
|
||||
|
||||
true_compile = Template.compile
|
||||
@classmethod
|
||||
def cl_compile(kls, *args, **kwargs):
|
||||
kwargs['compilerClass'] = CompilerGetVars
|
||||
kwargs['useCache'] = False
|
||||
return true_compile(*args, **kwargs)
|
||||
Template.compile = cl_compile
|
||||
|
||||
def CompilerGetVar(varName, default=Unspecified):
|
||||
#remplace Cheetah's getVar function
|
||||
#this function permite to known variable if getVar is used
|
||||
if varName.startswith('%%'):
|
||||
raise Exception('varname should not start with %% {0}'.format(varName))
|
||||
global extra_vars, config
|
||||
config.read_only()
|
||||
try:
|
||||
option = config.creole.find_first(byname=varName)
|
||||
path = config.cfgimpl_get_description().impl_get_path_by_opt(option)
|
||||
value = getattr(config, path)
|
||||
except (AttributeError, ConfigError):
|
||||
try:
|
||||
option = config.creole.find_first(byname=varName, check_properties=False)
|
||||
path = config.cfgimpl_get_description().impl_get_path_by_opt(option)
|
||||
#populate_mandatory(config, option, path, raise_propertyerror=True)
|
||||
config.read_write()
|
||||
populate_mandatories()
|
||||
config.read_only()
|
||||
value = getattr(config, path)
|
||||
except (AttributeError, RequirementError), err:
|
||||
config.read_only()
|
||||
#support default value
|
||||
if default != Unspecified:
|
||||
return default
|
||||
else:
|
||||
raise AttributeError('option:', varName, ':', err)
|
||||
except PropertiesOptionError as err:
|
||||
if default != Unspecified:
|
||||
return default
|
||||
else:
|
||||
raise err
|
||||
except Exception as err:
|
||||
config.read_only()
|
||||
raise err
|
||||
except Exception as err:
|
||||
config.read_only()
|
||||
raise err
|
||||
lpath = '.'.join(path.split('.')[2:])
|
||||
dico = {lpath: value}
|
||||
engine = CreoleTemplateEngine(force_values=dico)
|
||||
name = path.split('.')[-1]
|
||||
extra_vars[option] = name
|
||||
if "." in lpath:
|
||||
spath = lpath.split('.')
|
||||
if spath[0] == spath[1]:
|
||||
ret = engine.creole_variables_dict[name]
|
||||
else:
|
||||
ret = engine.creole_variables_dict[spath[0]].slave[spath[1]]
|
||||
else:
|
||||
ret = engine.creole_variables_dict[name]
|
||||
return ret
|
||||
|
||||
def CompilerGetattr(creolemaster, name, default=None):
|
||||
if not isinstance(creolemaster, CreoleMaster):
|
||||
raise Exception('creolemaster must be CreoleMaster, not {0}'.format(type(creolemaster)))
|
||||
if name not in creolemaster.slave:
|
||||
#FIXME assume name is slave?
|
||||
value = CompilerGetVar(name, default)
|
||||
if creolemaster._index is not None:
|
||||
value = value[creolemaster._index]
|
||||
creolemaster.add_slave(name, value)
|
||||
return getattr(creolemaster, name, default)
|
||||
|
||||
#======================= EOSFUNC =======================
|
||||
eos = {}
|
||||
for func in dir(eosfunc):
|
||||
if not func.startswith('_'):
|
||||
eos[func] = getattr(eosfunc, func)
|
||||
|
||||
#======================= CONFIG =======================
|
||||
def populate_mandatory(config, option, path, raise_propertyerror=False):
|
||||
def _build_network(path):
|
||||
for num in range(0, 4):
|
||||
if path.startswith('creole.interface_{0}'.format(num)):
|
||||
return num
|
||||
#si il y a un test de consistence de type _cons_in_network (l'IP doit être dans un network défini)
|
||||
#on utilise le réseau de ce network #10714
|
||||
if getattr(option, '_consistencies', None) is not None:
|
||||
for const in option._consistencies:
|
||||
if const[0] == '_cons_in_network':
|
||||
try:
|
||||
opt = const[1][1]
|
||||
path = config.cfgimpl_get_description().impl_get_path_by_opt(opt)
|
||||
val = config.getattr(path, force_permissive=True)
|
||||
if isinstance(val, list):
|
||||
val = val[0]
|
||||
return val.split('.')[2]
|
||||
except IndexError:
|
||||
pass
|
||||
return 5
|
||||
def _build_ip(path):
|
||||
if path.endswith('_fichier_link'):
|
||||
return 3
|
||||
elif path.endswith('_proxy_link'):
|
||||
return 2
|
||||
else:
|
||||
#ne pas retourner la même valeur si elle est censé être différente
|
||||
if getattr(option, '_consistencies', None) is not None:
|
||||
for const in option._consistencies:
|
||||
if const[0] == '_cons_not_equal':
|
||||
return 4
|
||||
|
||||
return 1
|
||||
if option.impl_getname().startswith('nom_carte_eth'):
|
||||
value = unicode(option.impl_getname())
|
||||
elif isinstance(option, UnicodeOption):
|
||||
value = u'value'
|
||||
elif isinstance(option, IPOption):
|
||||
value = u'192.168.{0}.{1}'.format(_build_network(path), _build_ip(path))
|
||||
elif isinstance(option, NetworkOption):
|
||||
value = u'192.168.{0}.0'.format(_build_network(path))
|
||||
elif isinstance(option, NetmaskOption):
|
||||
value = u'255.255.255.0'
|
||||
elif isinstance(option, BroadcastOption):
|
||||
value = u'192.168.{0}.255'.format(_build_network(path))
|
||||
elif isinstance(option, EmailOption):
|
||||
value = u'foo@bar.com'
|
||||
elif isinstance(option, URLOption):
|
||||
value = u'http://foo.com/bar'
|
||||
elif isinstance(option, DomainnameOption):
|
||||
allow_without_dot = option._get_extra('_allow_without_dot')
|
||||
o_type = option._get_extra('_dom_type')
|
||||
if option._name == 'smb_workgroup':
|
||||
value = u'othervalue'
|
||||
elif o_type in ['netbios', 'hostname']:
|
||||
value = u'value'
|
||||
else:
|
||||
value = u'value.lan'
|
||||
elif isinstance(option, FilenameOption):
|
||||
value = u'/tmp/foo'
|
||||
elif isinstance(option, ChoiceOption):
|
||||
#FIXME devrait le faire tout seul non ?
|
||||
value = option.impl_get_values(config)[0]
|
||||
elif isinstance(option, IntOption):
|
||||
value = 1
|
||||
elif isinstance(option, PortOption):
|
||||
value = 80
|
||||
elif isinstance(option, DomainnameOption):
|
||||
value = 'foo.com'
|
||||
elif isinstance(option, UsernameOption):
|
||||
value = 'toto'
|
||||
elif isinstance(option, PasswordOption):
|
||||
value = 'P@ssWord'
|
||||
else:
|
||||
raise Exception('the Tiramisu type {0} is not supported by CreoleLint (variable : {1})'.format(type(option), path))
|
||||
validator = option.impl_get_validator()
|
||||
if validator is not None and validator[0] == valid_regexp:
|
||||
regexp = validator[1][''][0]
|
||||
# génération d'une "value" valide
|
||||
# en cas de valid_regexp sans valeur par défaut
|
||||
if regexp == u'^[A-Z][0-9]$':
|
||||
value = u'A1'
|
||||
elif option._name == 'additional_repository_source':
|
||||
# variable avec expression (très) spécifique #20291
|
||||
value = u"deb http://test dist"
|
||||
elif not regexp.startswith(u'^[a-z0-9]') and regexp.startswith('^'):
|
||||
value = regexp[1:]
|
||||
if option.impl_is_multi():
|
||||
if option.impl_is_master_slaves('slave'):
|
||||
#slave should have same length as master
|
||||
masterpath = '.'.join(path.split('.')[:-1]+[path.split('.')[-2]])
|
||||
try:
|
||||
len_master = len(getattr(config, masterpath))
|
||||
val = []
|
||||
for i in range(0, len_master):
|
||||
val.append(value)
|
||||
value = val
|
||||
except:
|
||||
value = [value]
|
||||
else:
|
||||
value = [value]
|
||||
try:
|
||||
config.setattr(path, value, force_permissive=True)
|
||||
except ValueError, err:
|
||||
msg = str('error for {0} type {1}: {2}'.format(path, type(option), err))
|
||||
raise Exception(msg)
|
||||
except PropertiesOptionError, err:
|
||||
if 'frozen' not in err.proptype:
|
||||
if raise_propertyerror:
|
||||
raise err
|
||||
msg = str('error for {0} type {1}: {2}'.format(path, type(option), err))
|
||||
raise Exception(msg)
|
||||
|
||||
|
||||
class Reload(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Check_Template:
|
||||
|
||||
def __init__(self, template_name):
|
||||
self.all_requires = {}
|
||||
self.current_opt = {}
|
||||
self.od_list = {}
|
||||
global extra_vars
|
||||
#reinit extra_vars
|
||||
extra_vars = {}
|
||||
self.old_dico = []
|
||||
self.current_var = []
|
||||
self.ori_options = []
|
||||
self.file_path = None
|
||||
self.template_name = template_name
|
||||
self.current_container = client.get_container_infos('mail')
|
||||
self.tmpl = None
|
||||
self.is_tmpl = False
|
||||
self.filename_ok = False
|
||||
|
||||
|
||||
def populate_requires(self, option, path, force=False):
|
||||
def _parse_requires(_option):
|
||||
o_requires = _option.impl_getrequires()
|
||||
if o_requires is not None:
|
||||
for requires in o_requires:
|
||||
for require in requires:
|
||||
opt_ = require[0]
|
||||
path_ = config.cfgimpl_get_description().impl_get_path_by_opt(opt_)
|
||||
self.populate_requires(opt_, path_, force=True)
|
||||
if not force and not path.startswith('creole.'):
|
||||
return
|
||||
if option in self.current_opt:
|
||||
return
|
||||
o_requires = option.impl_getrequires()
|
||||
if o_requires is not None:
|
||||
for requires in o_requires:
|
||||
for require in requires:
|
||||
if require[0].impl_is_master_slaves('slave'):
|
||||
path_ = config.cfgimpl_get_description().impl_get_path_by_opt(require[0])
|
||||
s_path = path_.split('.')
|
||||
master_path = 'creole.' + s_path[1] + '.' + s_path[2] + '.' + s_path[2]
|
||||
try:
|
||||
opt_master = config.unwrap_from_path(master_path)
|
||||
config.cfgimpl_get_settings().remove('everything_frozen')
|
||||
populate_mandatory(config, opt_master, master_path)
|
||||
except:
|
||||
pass
|
||||
self.all_requires.setdefault(option, []).append(require[0])
|
||||
if isinstance(option, OptionDescription):
|
||||
self.od_list[path] = option
|
||||
if force and not option._name in self.current_var:
|
||||
self.current_var.append(option._name)
|
||||
if option._name in self.current_var or not path.startswith('creole.'):
|
||||
if not isinstance(option, OptionDescription):
|
||||
if path.startswith('creole.'):
|
||||
self.current_opt[option] = '.'.join(path.split('.')[1:])
|
||||
else:
|
||||
self.current_opt[option] = None
|
||||
_parse_requires(option)
|
||||
#requires could be in parent's too
|
||||
opath = ''
|
||||
for parent in path.split('.')[:-1]:
|
||||
opath += parent
|
||||
if opath in self.od_list:
|
||||
desc = self.od_list[opath]
|
||||
self.current_opt[desc] = None
|
||||
_parse_requires(desc)
|
||||
opath += '.'
|
||||
try:
|
||||
if option._callback is not None:
|
||||
for params in option._callback[1].values():
|
||||
for param in params:
|
||||
if isinstance(param, tuple):
|
||||
opt = param[0]
|
||||
path = config.cfgimpl_get_description().impl_get_path_by_opt(opt)
|
||||
self.populate_requires(opt, path, force=True)
|
||||
except (AttributeError, KeyError):
|
||||
pass
|
||||
|
||||
def read_write(self):
|
||||
config.read_write()
|
||||
config.cfgimpl_get_settings().remove('disabled')
|
||||
config.cfgimpl_get_settings().remove('hidden')
|
||||
config.cfgimpl_get_settings().remove('frozen')
|
||||
|
||||
def change_value(self, path, value, multi, parse_message, option):
|
||||
self.read_write()
|
||||
config.cfgimpl_get_settings()[option].remove('force_default_on_freeze')
|
||||
if multi:
|
||||
if option.impl_is_master_slaves('slave'):
|
||||
s_path = path.split('.')
|
||||
master_path = s_path[0] + '.' + s_path[1] + '.' + s_path[2] + '.' + s_path[2]
|
||||
master_option = config.cfgimpl_get_description().impl_get_opt_by_path(master_path)
|
||||
if getattr(config, master_path) == []:
|
||||
populate_mandatory(config, master_option, master_path)
|
||||
value = [value]
|
||||
if parse_message:
|
||||
print parse_message, value
|
||||
setattr(config, path, value)
|
||||
config.read_only()
|
||||
|
||||
def template(self):
|
||||
self.last_notfound = []
|
||||
def get_value(opt_, path_):
|
||||
try:
|
||||
return getattr(config.creole, path_)
|
||||
except PropertiesOptionError, err:
|
||||
if err.proptype == ['mandatory']:
|
||||
self.read_write()
|
||||
config.cfgimpl_get_settings().remove('mandatory')
|
||||
s_path = path_.split('.')
|
||||
#set value to master
|
||||
if len(s_path) == 3 and s_path[1] != s_path[2]:
|
||||
master_path = 'creole.' + s_path[0] + '.' + s_path[1] + '.' + s_path[1]
|
||||
opt_master = config.unwrap_from_path(master_path)
|
||||
populate_mandatory(config, opt_master, master_path)
|
||||
populate_mandatory(config, opt_, 'creole.' + path_)
|
||||
config.read_only()
|
||||
config.cfgimpl_get_settings().remove('mandatory')
|
||||
try:
|
||||
ret = getattr(config.creole, path_)
|
||||
config.cfgimpl_get_settings().append('mandatory')
|
||||
return ret
|
||||
except PropertiesOptionError:
|
||||
pass
|
||||
raise NotFound('no value')
|
||||
except ConfigError:
|
||||
self.read_write()
|
||||
populate_mandatory(config, opt_, 'creole.' + path_)
|
||||
config.read_only()
|
||||
try:
|
||||
return getattr(config.creole, path_)
|
||||
except ConfigError, err:
|
||||
raise err
|
||||
except PropertiesOptionError, err:
|
||||
raise NotFound('no value')
|
||||
try:
|
||||
is_gen_file = getattr(config, self.file_path)
|
||||
except PropertiesOptionError, err:
|
||||
is_gen_file = False
|
||||
if not is_gen_file:
|
||||
return
|
||||
try:
|
||||
config.read_write()
|
||||
populate_mandatories()
|
||||
config.read_only()
|
||||
dico = {}
|
||||
for opt_, path_ in self.current_opt.items():
|
||||
#path_ is None if it's an OptionDescription
|
||||
if path_ is None:
|
||||
continue
|
||||
try:
|
||||
dico[path_] = get_value(opt_, path_)
|
||||
except NotFound:
|
||||
pass
|
||||
#FIXME revoir le strip_full_path
|
||||
ndico = {}
|
||||
for path_, value in dico.items():
|
||||
sdico = path_.split('.')
|
||||
if len(sdico) == 2:
|
||||
ndico[sdico[1]] = value
|
||||
elif len(sdico) == 3:
|
||||
if sdico[1] == sdico[2]:
|
||||
ndico[sdico[1]] = value
|
||||
else:
|
||||
ndico['.'.join(sdico[1:])] = value
|
||||
else:
|
||||
raise Exception('chemin de longueur inconnu {}'.format(path_))
|
||||
engine = CreoleTemplateEngine(force_values=ndico)
|
||||
dico = engine.creole_variables_dict
|
||||
self.read_write()
|
||||
except ConfigError, err:
|
||||
msg = 'erreur de templating', err
|
||||
raise ValueError(msg)
|
||||
diff = True
|
||||
for old in self.old_dico:
|
||||
if dico.keys() == old.keys():
|
||||
for key in old.keys():
|
||||
if old[key] != dico[key]:
|
||||
diff = False
|
||||
break
|
||||
if not diff:
|
||||
break
|
||||
if not diff:
|
||||
return
|
||||
try:
|
||||
self.old_dico.append(dico)
|
||||
searchlist = [dico, eos, {'is_defined' : IsDefined(dico),
|
||||
'creole_client' : CreoleClient(),
|
||||
'current_container': CreoleGet(self.current_container),
|
||||
}]
|
||||
rtmpl = self.tmpl(searchList=searchlist)
|
||||
rtmpl.getVar = CompilerGetVar
|
||||
rtmpl.getattr = CompilerGetattr
|
||||
rtmpl = str(rtmpl)
|
||||
#print rtmpl
|
||||
self.is_tmpl = True
|
||||
except NotFound, err:
|
||||
lst = getVars()
|
||||
if lst == []:
|
||||
raise Exception("Il manque une option", err, 'avec le dictionnaire', dico)
|
||||
for ls in lst:
|
||||
try:
|
||||
CompilerGetVar(ls)
|
||||
except AttributeError:
|
||||
self.last_notfound.append(ls)
|
||||
raise Reload('')
|
||||
except Exception, err:
|
||||
raise Exception("Il y a une erreur", err, 'avec le dictionnaire', dico)
|
||||
|
||||
def check_reload_with_extra(self):
|
||||
#if extra_vars has value, check if not already in current_opt
|
||||
global extra_vars
|
||||
if extra_vars != {}:
|
||||
oret = set(extra_vars.keys())
|
||||
opt_requires = oret & set(self.all_requires.keys())
|
||||
for opt_ in opt_requires:
|
||||
oret.update(self.all_requires[opt_])
|
||||
dont_exists = set(oret) - set(self.current_opt.keys())
|
||||
ret = []
|
||||
for opt_ in dont_exists:
|
||||
try:
|
||||
ret.append(extra_vars[opt_])
|
||||
except KeyError:
|
||||
ret.append(opt_._name)
|
||||
extra_vars = {}
|
||||
if ret == []:
|
||||
return None
|
||||
return ret
|
||||
|
||||
def test_all_values_for(self, options, cpt):
|
||||
option = options[0]
|
||||
parse_message = None
|
||||
if DEBUG:
|
||||
parse_message = '*' * cpt + '>' + option._name
|
||||
|
||||
if not isinstance(option, ChoiceOption):
|
||||
msg = str('pas simple la... ' + option._name)
|
||||
raise NotImplementedError(msg)
|
||||
multi = option.impl_is_multi()
|
||||
path = config.cfgimpl_get_description().impl_get_path_by_opt(option)
|
||||
for value in option.impl_get_values(config):
|
||||
self.change_value(path, value, multi, parse_message, option)
|
||||
if options[1:] != []:
|
||||
#if already value to test, restart test_all_values_for
|
||||
ret = self.test_all_values_for(options[1:], cpt + 1)
|
||||
if ret != None:
|
||||
return ret
|
||||
else:
|
||||
need_reload = False
|
||||
try:
|
||||
self.template()
|
||||
except Reload:
|
||||
need_reload = True
|
||||
ret = self.check_reload_with_extra()
|
||||
if need_reload and ret is None:
|
||||
notfound = []
|
||||
paths = config.cfgimpl_get_description()._cache_paths[1]
|
||||
for ls in self.last_notfound:
|
||||
#if variable is locale (means template) variable, not config's one
|
||||
for path in paths:
|
||||
if path.endswith('.' + ls):
|
||||
notfound.append(ls)
|
||||
break
|
||||
if notfound != []:
|
||||
raise Exception('variable not found after reload {0}'.format(notfound))
|
||||
if ret is not None:
|
||||
return ret
|
||||
|
||||
|
||||
def open_file(self, force_var):
|
||||
# Open template and compile it
|
||||
# retrieve template vars (add force_var if needed)
|
||||
filecontent = open(self.template_name).read()
|
||||
#try to convert content in unicode
|
||||
self.tmpl = Template.compile(filecontent, compilerSettings=compilerSettings) # ,
|
||||
#compilerClass=CompilerGetVars)
|
||||
self.current_var = getVars()
|
||||
if force_var:
|
||||
self.current_var.extend(force_var)
|
||||
|
||||
def populate_file(self, path, option):
|
||||
if path.startswith('containers.files.file'):
|
||||
if path.endswith('.source') and option.impl_getdefault().endswith('/{0}'.format(self.template_name.split('/')[-1])):
|
||||
self.filename_ok = True
|
||||
if self.filename_ok and path.endswith('.activate'):
|
||||
self.file_path = path
|
||||
self.filename_ok = False
|
||||
self.populate_requires(option, path, force=True)
|
||||
|
||||
def test_all_values(self):
|
||||
try:
|
||||
options = list(set(self.all_requires.keys())&set(self.current_opt.keys()))
|
||||
need_tmpl = False
|
||||
if options != []:
|
||||
requires_options = set()
|
||||
for opt in options:
|
||||
for op in self.all_requires[opt]:
|
||||
if 'frozen' not in config.cfgimpl_get_settings()[op]:
|
||||
requires_options.add(op)
|
||||
if requires_options == set([]):
|
||||
need_tmpl = True
|
||||
else:
|
||||
self.ori_options = requires_options
|
||||
ret = self.test_all_values_for(list(requires_options), 0)
|
||||
if ret is not None:
|
||||
if DEBUG:
|
||||
print "reload with", ret
|
||||
self.check_template(ret, already_load=True)
|
||||
else:
|
||||
need_tmpl = True
|
||||
|
||||
if need_tmpl is True:
|
||||
try:
|
||||
self.template()
|
||||
except:
|
||||
self.test_all_values()
|
||||
except Exception, err:
|
||||
if DEBUG:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
msg = self.template_name, ':', err
|
||||
raise Exception(msg)
|
||||
|
||||
def check_template(self, force_var=None, already_load=False):
|
||||
#remove all modification (value, properties, ...)
|
||||
open_error = None
|
||||
try:
|
||||
self.open_file(force_var)
|
||||
except Exception, err:
|
||||
open_error = "problème à l'ouverture du fichier {}".format(self.template_name)
|
||||
|
||||
config.read_only()
|
||||
for index, option in enumerate(config.cfgimpl_get_description()._cache_paths[0]):
|
||||
path = config.cfgimpl_get_description()._cache_paths[1][index]
|
||||
self.populate_file(path, option)
|
||||
self.populate_requires(option, path)
|
||||
if self.file_path is None:
|
||||
if open_error is not None:
|
||||
print "le fichier {0} non présent dans un dictionnaire a un problème : {1}".format(basename(self.template_name),
|
||||
open_error)
|
||||
else:
|
||||
print " \\-- fichier non présent dans un dictionnaire {0}".format(self.template_name)
|
||||
return
|
||||
if open_error is not None:
|
||||
raise Exception(open_error)
|
||||
|
||||
if not already_load:
|
||||
print " \\--", self.template_name
|
||||
self.test_all_values()
|
||||
if not self.is_tmpl:
|
||||
print "pas de templating !"
|
||||
|
||||
|
||||
def populate_mandatories():
|
||||
for path in config.cfgimpl_get_values().mandatory_warnings(config):
|
||||
if path.startswith('creole.'):
|
||||
option = config.cfgimpl_get_description().impl_get_opt_by_path(path)
|
||||
try:
|
||||
populate_mandatory(config, option, path)
|
||||
except PropertiesOptionError:
|
||||
pass
|
||||
|
||||
|
||||
def parse_templates(templates_name):
|
||||
global config, cl_chunks, cl_vars, extra_vars
|
||||
config = creole_loader(load_values=False, load_extra=True)
|
||||
config.read_write()
|
||||
populate_mandatories()
|
||||
cfg = config
|
||||
for template_name in templates_name:
|
||||
cl_chunks = set()
|
||||
cl_vars = set()
|
||||
extra_vars = {}
|
||||
config = cfg.duplicate()
|
||||
config.read_write()
|
||||
populate_mandatories()
|
||||
ctmpl = Check_Template(template_name)
|
||||
try:
|
||||
ctmpl.check_template()
|
||||
except Exception, err:
|
||||
if DEBUG:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
print_red(str(err))
|
||||
sys.exit(1)
|
||||
|
@ -1,125 +0,0 @@
|
||||
"""
|
||||
Implements terminal reporting of the full validation process.
|
||||
|
||||
Implements the various reporting hooks.
|
||||
XXX: Currently in progress, NOT IN WORKING STATE.
|
||||
|
||||
"""
|
||||
import sys
|
||||
|
||||
def pytest_addoption(parser):
|
||||
group = parser.getgroup("terminal reporting", after="general")
|
||||
group._addoption('-v', '--verbose', action="count",
|
||||
dest="verbose", default=0, help="increase verbosity."),
|
||||
group.addoption('--report',
|
||||
action="store", dest="report", default=None, metavar="opts",
|
||||
help="comma separated options, valid: skipped,xfailed")
|
||||
group._addoption('--fulltrace',
|
||||
action="store_true", dest="fulltrace", default=False,
|
||||
help="don't cut any tracebacks (default is to cut).")
|
||||
|
||||
group.addoption('--traceconfig',
|
||||
action="store_true", dest="traceconfig", default=False,
|
||||
help="trace considerations of conftest.py files."),
|
||||
|
||||
class TerminalReporter:
|
||||
def __init__(self, config, file=None):
|
||||
self.config = config
|
||||
self.stats = {}
|
||||
self.curdir = py.path.local()
|
||||
if file is None:
|
||||
file = sys.stdout
|
||||
self._tw = TerminalWriter(file)
|
||||
self.currentfspath = None
|
||||
self._reportopt = getreportopt(config.getvalue('report'))
|
||||
|
||||
def hasopt(self, name):
|
||||
return self._reportopt.get(name, False)
|
||||
|
||||
def write_fspath_result(self, fspath, res):
|
||||
fspath = self.curdir.bestrelpath(fspath)
|
||||
if fspath != self.currentfspath:
|
||||
self._tw.line()
|
||||
relpath = self.curdir.bestrelpath(fspath)
|
||||
self._tw.write(relpath + " ")
|
||||
self.currentfspath = fspath
|
||||
self._tw.write(res)
|
||||
|
||||
def write_ensure_prefix(self, prefix, extra="", **kwargs):
|
||||
if self.currentfspath != prefix:
|
||||
self._tw.line()
|
||||
self.currentfspath = prefix
|
||||
self._tw.write(prefix)
|
||||
if extra:
|
||||
self._tw.write(extra, **kwargs)
|
||||
self.currentfspath = -2
|
||||
|
||||
def ensure_newline(self):
|
||||
if self.currentfspath:
|
||||
self._tw.line()
|
||||
self.currentfspath = None
|
||||
|
||||
def write_line(self, line, **markup):
|
||||
line = str(line)
|
||||
self.ensure_newline()
|
||||
self._tw.line(line, **markup)
|
||||
|
||||
def write_sep(self, sep, title=None, **markup):
|
||||
self.ensure_newline()
|
||||
self._tw.sep(sep, title, **markup)
|
||||
|
||||
def getoutcomeword(self, rep):
|
||||
if rep.passed:
|
||||
return "PASS", dict(green=True)
|
||||
elif rep.failed:
|
||||
return "FAIL", dict(red=True)
|
||||
elif rep.skipped:
|
||||
return "SKIP"
|
||||
else:
|
||||
return "???", dict(red=True)
|
||||
|
||||
#
|
||||
# summaries for sessionfinish
|
||||
#
|
||||
|
||||
def summary_failures(self):
|
||||
if 'failed' in self.stats and self.config.option.tbstyle != "no":
|
||||
self.write_sep("=", "FAILURES")
|
||||
for rep in self.stats['failed']:
|
||||
msg = self._getfailureheadline(rep)
|
||||
self.write_sep("_", msg)
|
||||
self.write_platinfo(rep)
|
||||
rep.toterminal(self._tw)
|
||||
|
||||
def summary_errors(self):
|
||||
if 'error' in self.stats and self.config.option.tbstyle != "no":
|
||||
self.write_sep("=", "ERRORS")
|
||||
for rep in self.stats['error']:
|
||||
msg = self._getfailureheadline(rep)
|
||||
if not hasattr(rep, 'when'):
|
||||
# collect
|
||||
msg = "ERROR during collection " + msg
|
||||
elif rep.when == "setup":
|
||||
msg = "ERROR at setup of " + msg
|
||||
elif rep.when == "teardown":
|
||||
msg = "ERROR at teardown of " + msg
|
||||
self.write_sep("_", msg)
|
||||
self.write_platinfo(rep)
|
||||
rep.toterminal(self._tw)
|
||||
|
||||
def summary_stats(self):
|
||||
session_duration = py.std.time.time() - self._sessionstarttime
|
||||
|
||||
keys = "failed passed skipped deselected".split()
|
||||
for key in self.stats.keys():
|
||||
if key not in keys:
|
||||
keys.append(key)
|
||||
parts = []
|
||||
for key in keys:
|
||||
val = self.stats.get(key, None)
|
||||
if val:
|
||||
parts.append("%d %s" %(len(val), key))
|
||||
line = ", ".join(parts)
|
||||
# XXX coloring
|
||||
self.write_sep("=", "%s in %.2f seconds" %(line, session_duration))
|
||||
|
@ -1,139 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
|
||||
Helper functions for writing to terminals and files.
|
||||
XXX: Currently in progress, NOT IN WORKING STATE.
|
||||
|
||||
"""
|
||||
|
||||
import sys, os
|
||||
|
||||
def _getdimensions():
|
||||
import termios,fcntl,struct
|
||||
call = fcntl.ioctl(0,termios.TIOCGWINSZ,"\000"*8)
|
||||
height,width = struct.unpack( "hhhh", call ) [:2]
|
||||
return height, width
|
||||
|
||||
def get_terminal_width():
|
||||
try:
|
||||
height, width = _getdimensions()
|
||||
except (SystemExit, KeyboardInterrupt):
|
||||
raise
|
||||
except:
|
||||
# FALLBACK
|
||||
width = int(os.environ.get('COLUMNS', 80))-1
|
||||
# XXX the windows getdimensions may be bogus, let's sanify a bit
|
||||
width = max(width, 40) # we alaways need 40 chars
|
||||
return width
|
||||
|
||||
terminal_width = get_terminal_width()
|
||||
|
||||
# XXX unify with _escaped func below
|
||||
def ansi_print(text, file=None, newline=True, flush=False):
|
||||
if file is None:
|
||||
file = sys.stderr
|
||||
text = text.strip()
|
||||
if newline:
|
||||
text += '\n'
|
||||
file.write(text)
|
||||
if flush:
|
||||
file.flush()
|
||||
if file:
|
||||
file.close()
|
||||
|
||||
def should_do_markup(file):
|
||||
return hasattr(file, 'isatty') and file.isatty() \
|
||||
and os.environ.get('TERM') != 'dumb'
|
||||
|
||||
class TerminalWriter(object):
|
||||
_esctable = dict(black=30, red=31, green=32, yellow=33,
|
||||
blue=34, purple=35, cyan=36, white=37,
|
||||
Black=40, Red=41, Green=42, Yellow=43,
|
||||
Blue=44, Purple=45, Cyan=46, White=47,
|
||||
bold=1, light=2, blink=5, invert=7)
|
||||
|
||||
def __init__(self, file=None, encoding=None):
|
||||
self.encoding = encoding
|
||||
|
||||
if file is None:
|
||||
file = sys.stdout
|
||||
|
||||
elif hasattr(file, '__call__'):
|
||||
file = WriteFile(file, encoding=encoding)
|
||||
self._file = file
|
||||
self.fullwidth = get_terminal_width()
|
||||
self.hasmarkup = should_do_markup(file)
|
||||
|
||||
def _escaped(self, text, esc):
|
||||
if esc and self.hasmarkup:
|
||||
text = (''.join(['\x1b[%sm' % cod for cod in esc]) +
|
||||
text +'\x1b[0m')
|
||||
return text
|
||||
|
||||
def markup(self, text, **kw):
|
||||
esc = []
|
||||
for name in kw:
|
||||
if name not in self._esctable:
|
||||
raise ValueError("unknown markup: %r" %(name,))
|
||||
if kw[name]:
|
||||
esc.append(self._esctable[name])
|
||||
return self._escaped(text, tuple(esc))
|
||||
|
||||
def sep(self, sepchar, title=None, fullwidth=None, **kw):
|
||||
if fullwidth is None:
|
||||
fullwidth = self.fullwidth
|
||||
# the goal is to have the line be as long as possible
|
||||
# under the condition that len(line) <= fullwidth
|
||||
if title is not None:
|
||||
# we want 2 + 2*len(fill) + len(title) <= fullwidth
|
||||
# i.e. 2 + 2*len(sepchar)*N + len(title) <= fullwidth
|
||||
# 2*len(sepchar)*N <= fullwidth - len(title) - 2
|
||||
# N <= (fullwidth - len(title) - 2) // (2*len(sepchar))
|
||||
N = (fullwidth - len(title) - 2) // (2*len(sepchar))
|
||||
fill = sepchar * N
|
||||
line = "%s %s %s" % (fill, title, fill)
|
||||
else:
|
||||
# we want len(sepchar)*N <= fullwidth
|
||||
# i.e. N <= fullwidth // len(sepchar)
|
||||
line = sepchar * (fullwidth // len(sepchar))
|
||||
# in some situations there is room for an extra sepchar at the right,
|
||||
# in particular if we consider that with a sepchar like "_ " the
|
||||
# trailing space is not important at the end of the line
|
||||
if len(line) + len(sepchar.rstrip()) <= fullwidth:
|
||||
line += sepchar.rstrip()
|
||||
|
||||
self.line(line, **kw)
|
||||
|
||||
def write(self, s, **kw):
|
||||
if s:
|
||||
s = self._getbytestring(s)
|
||||
if self.hasmarkup and kw:
|
||||
s = self.markup(s, **kw)
|
||||
self._file.write(s)
|
||||
self._file.flush()
|
||||
|
||||
def _getbytestring(self, s):
|
||||
# XXX review this and the whole logic
|
||||
if self.encoding and sys.version_info < (3,0) and isinstance(s, unicode):
|
||||
return s.encode(self.encoding)
|
||||
elif not isinstance(s, str):
|
||||
return str(s)
|
||||
return s
|
||||
|
||||
def line(self, s='', **kw):
|
||||
self.write(s, **kw)
|
||||
self.write('\n')
|
||||
|
||||
class WriteFile(object):
|
||||
def __init__(self, writemethod, encoding=None):
|
||||
self.encoding = encoding
|
||||
self._writemethod = writemethod
|
||||
|
||||
def write(self, data):
|
||||
if self.encoding:
|
||||
data = data.encode(self.encoding)
|
||||
self._writemethod(data)
|
||||
|
||||
def flush(self):
|
||||
return
|
||||
|
@ -1,34 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
from creole.lint import warnsymb
|
||||
|
||||
|
||||
class Warn:
|
||||
|
||||
def __init__(self, write_level, itemname, warnno, comment, checks):
|
||||
self.warnno = warnno
|
||||
self.comment = comment
|
||||
self.checks = checks
|
||||
self.write_level = getattr(warnsymb, write_level)
|
||||
|
||||
def to_dict(self):
|
||||
"""
|
||||
formats a msg warn directly from a warning message
|
||||
"""
|
||||
dico_loc = {}
|
||||
for var in self.checks:
|
||||
if hasattr(var, 'location'):
|
||||
locs = var.location
|
||||
for vfile, vline in locs:
|
||||
if vfile == 'dictionnaire':
|
||||
raise Exception('vfile ne doit pas se nommer dictionnaire !!!')
|
||||
if not dico_loc.has_key(vfile):
|
||||
dico_loc[vfile] = []
|
||||
dico_loc[vfile].append((vline, var))
|
||||
else:
|
||||
if not dico_loc.has_key('dictionnaire'):
|
||||
dico_loc['dictionnaire'] = []
|
||||
dico_loc['dictionnaire'].append((None, var))
|
||||
# ret = ["[%s:%s:%s] %s : %s (dictionnaire)" %(level, name, self.itemname, self.comment, vname)]
|
||||
return dico_loc
|
@ -1,33 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Standard errno symbols
|
||||
"""
|
||||
|
||||
"""Dictionary providing a mapping from the errno value to the string
|
||||
name in the underlying waring. For instance,
|
||||
errno.errorcode[errno.EPERM] maps to 'EPERM'."""
|
||||
|
||||
errorlevel = {
|
||||
1: 'error',
|
||||
2: 'warning',
|
||||
3: 'info',
|
||||
}
|
||||
|
||||
errorcode = {
|
||||
1: ('ERROR', 1),
|
||||
2: ('WARNING', 2),
|
||||
3: ('INFO', 3),
|
||||
4: ('NAME', 1),
|
||||
5: ('NAME', 2),
|
||||
6: ('NAME', 3),
|
||||
7: ('UNUSED', 1),
|
||||
8: ('UNUSED', 2),
|
||||
9: ('UNUSED', 3),
|
||||
}
|
||||
|
||||
globs = globals()
|
||||
|
||||
for key, value in errorlevel.items():
|
||||
globs[value] = key
|
||||
|
||||
|
@ -1,607 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Gestion du mini-langage de template
|
||||
On travaille sur les fichiers cibles
|
||||
"""
|
||||
|
||||
import sys
|
||||
import shutil
|
||||
import logging
|
||||
|
||||
import traceback
|
||||
import os
|
||||
from os import listdir, unlink
|
||||
from os.path import basename, join
|
||||
|
||||
from tempfile import mktemp
|
||||
|
||||
from Cheetah import Parser
|
||||
# l'encoding du template est déterminé par une regexp (encodingDirectiveRE dans Parser.py)
|
||||
# il cherche un ligne qui ressemble à '#encoding: utf-8
|
||||
# cette classe simule le module 're' et retourne toujours l'encoding utf-8
|
||||
# 6224
|
||||
class FakeEncoding():
|
||||
def groups(self):
|
||||
return ('utf-8',)
|
||||
|
||||
def search(self, *args):
|
||||
return self
|
||||
Parser.encodingDirectiveRE = FakeEncoding()
|
||||
|
||||
from Cheetah.Template import Template as ChtTemplate
|
||||
from Cheetah.NameMapper import NotFound as CheetahNotFound
|
||||
|
||||
from config import patch_dir, templatedir, distrib_dir
|
||||
|
||||
from .client import CreoleClient, CreoleClientError
|
||||
from .error import FileNotFound, TemplateError, TemplateDisabled
|
||||
import eosfunc
|
||||
|
||||
from .i18n import _
|
||||
|
||||
import pyeole
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
log.addHandler(logging.NullHandler())
|
||||
|
||||
class IsDefined(object):
|
||||
"""
|
||||
filtre permettant de ne pas lever d'exception au cas où
|
||||
la variable Creole n'est pas définie
|
||||
"""
|
||||
def __init__(self, context):
|
||||
self.context = context
|
||||
|
||||
def __call__(self, varname):
|
||||
if '.' in varname:
|
||||
splitted_var = varname.split('.')
|
||||
if len(splitted_var) != 2:
|
||||
msg = _(u"Group variables must be of type master.slave")
|
||||
raise KeyError(msg)
|
||||
master, slave = splitted_var
|
||||
if master in self.context:
|
||||
return slave in self.context[master].slave.keys()
|
||||
return False
|
||||
else:
|
||||
return varname in self.context
|
||||
|
||||
|
||||
class CreoleGet(object):
|
||||
def __init__(self, context):
|
||||
self.context = context
|
||||
|
||||
def __call__(self, varname):
|
||||
return self.context[varname]
|
||||
|
||||
def __getitem__(self, varname):
|
||||
"""For bracket and dotted notation
|
||||
"""
|
||||
return self.context[varname]
|
||||
|
||||
def __contains__(self, varname):
|
||||
"""Check variable existence in context
|
||||
"""
|
||||
return varname in self.context
|
||||
|
||||
|
||||
@classmethod
|
||||
def cl_compile(kls, *args, **kwargs):
|
||||
kwargs['compilerSettings'] = {'directiveStartToken' : u'%',
|
||||
'cheetahVarStartToken' : u'%%',
|
||||
'EOLSlurpToken' : u'%',
|
||||
'PSPStartToken' : u'µ' * 10,
|
||||
'PSPEndToken' : u'µ' * 10,
|
||||
'commentStartToken' : u'µ' * 10,
|
||||
'commentEndToken' : u'µ' * 10,
|
||||
'multiLineCommentStartToken' : u'µ' * 10,
|
||||
'multiLineCommentEndToken' : u'µ' * 10}
|
||||
return kls.old_compile(*args, **kwargs)
|
||||
ChtTemplate.old_compile = ChtTemplate.compile
|
||||
ChtTemplate.compile = cl_compile
|
||||
|
||||
|
||||
class CheetahTemplate(ChtTemplate):
|
||||
"""classe pour personnaliser et faciliter la construction
|
||||
du template Cheetah
|
||||
"""
|
||||
def __init__(self, filename, context, current_container):
|
||||
"""Initialize Creole CheetahTemplate
|
||||
|
||||
@param filename: name of the file to process
|
||||
@type filename: C{str}
|
||||
@param context: flat dictionary of creole variables as 'name':'value',
|
||||
@type context: C{dict}
|
||||
@param current_container: flat dictionary describing the current container
|
||||
@type current_container: C{dict}
|
||||
"""
|
||||
eos = {}
|
||||
for func in dir(eosfunc):
|
||||
if not func.startswith('_'):
|
||||
eos[func] = getattr(eosfunc, func)
|
||||
# ajout des variables decrivant les conteneurs
|
||||
#FIXME chercher les infos dans le client !
|
||||
ChtTemplate.__init__(self, file=filename,
|
||||
searchList=[context, eos, {u'is_defined' : IsDefined(context),
|
||||
u'creole_client' : CreoleClient(),
|
||||
u'current_container':CreoleGet(current_container),
|
||||
}])
|
||||
|
||||
|
||||
class CreoleMaster(object):
|
||||
def __init__(self, value, slave=None, index=None):
|
||||
"""
|
||||
On rend la variable itérable pour pouvoir faire:
|
||||
for ip in iplist:
|
||||
print ip.network
|
||||
print ip.netmask
|
||||
print ip
|
||||
index is used for CreoleLint
|
||||
"""
|
||||
self._value = value
|
||||
if slave is not None:
|
||||
self.slave = slave
|
||||
else:
|
||||
self.slave = {}
|
||||
self._index = index
|
||||
|
||||
def __getattr__(self, name):
|
||||
"""Get slave variable or attribute of master value.
|
||||
|
||||
If the attribute is a name of a slave variable, return its value.
|
||||
Otherwise, returns the requested attribute of master value.
|
||||
"""
|
||||
if name in self.slave:
|
||||
value = self.slave[name]
|
||||
if isinstance(value, Exception):
|
||||
raise value
|
||||
return value
|
||||
else:
|
||||
return getattr(self._value, name)
|
||||
|
||||
def __getitem__(self, index):
|
||||
"""Get a master.slave at requested index.
|
||||
"""
|
||||
ret = {}
|
||||
for key, values in self.slave.items():
|
||||
ret[key] = values[index]
|
||||
return CreoleMaster(self._value[index], ret, index)
|
||||
|
||||
def __iter__(self):
|
||||
"""Iterate over master.slave.
|
||||
|
||||
Return synchronised value of master.slave.
|
||||
"""
|
||||
for i in range(len(self._value)):
|
||||
ret = {}
|
||||
for key, values in self.slave.items():
|
||||
ret[key] = values[i]
|
||||
yield CreoleMaster(self._value[i], ret, i)
|
||||
|
||||
def __len__(self):
|
||||
"""Delegate to master value
|
||||
"""
|
||||
return len(self._value)
|
||||
|
||||
def __repr__(self):
|
||||
"""Show CreoleMaster as dictionary.
|
||||
|
||||
The master value is stored under 'value' key.
|
||||
The slaves are stored under 'slave' key.
|
||||
"""
|
||||
return repr({u'value': self._value, u'slave': self.slave})
|
||||
|
||||
def __eq__(self, value):
|
||||
return value == self._value
|
||||
|
||||
def __ne__(self, value):
|
||||
return value != self._value
|
||||
|
||||
def __lt__(self, value):
|
||||
return self._value < value
|
||||
|
||||
def __le__(self, value):
|
||||
return self._value <= value
|
||||
|
||||
def __gt__(self, value):
|
||||
return self._value > value
|
||||
|
||||
def __ge__(self, value):
|
||||
return self._value >= value
|
||||
|
||||
def __str__(self):
|
||||
"""Delegate to master value
|
||||
"""
|
||||
return str(self._value)
|
||||
|
||||
def __add__(self, val):
|
||||
return self._value.__add__(val)
|
||||
|
||||
def __radd__(self, val):
|
||||
return val + self._value
|
||||
|
||||
def __contains__(self, item):
|
||||
return item in self._value
|
||||
|
||||
def add_slave(self, name, value):
|
||||
"""Add a slave variable
|
||||
|
||||
Minimal check on type and value of the slave in regards to the
|
||||
master one.
|
||||
|
||||
@param name: name of the slave variable
|
||||
@type name: C{str}
|
||||
@param value: value of the slave variable
|
||||
"""
|
||||
if isinstance(self._value, list):
|
||||
if not isinstance(value, list):
|
||||
raise TypeError
|
||||
elif len(value) != len(self._value):
|
||||
raise ValueError(_(u'length mismatch'))
|
||||
new_value = []
|
||||
for val in value:
|
||||
if isinstance(val, dict):
|
||||
new_value.append(ValueError(val['err']))
|
||||
else:
|
||||
new_value.append(val)
|
||||
value = new_value
|
||||
elif isinstance(value, list):
|
||||
raise TypeError
|
||||
self.slave[name] = value
|
||||
|
||||
class CreoleTemplateEngine(object):
|
||||
"""Engine to process Creole cheetah template
|
||||
"""
|
||||
def __init__(self, force_values=None):
|
||||
#force_values permit inject value and not used CreoleClient (used by CreoleLint)
|
||||
self.client = CreoleClient()
|
||||
self.creole_variables_dict = {}
|
||||
self.force_values = force_values
|
||||
self.load_eole_variables()
|
||||
|
||||
def load_eole_variables(self):
|
||||
# remplacement des variables EOLE
|
||||
self.creole_variables_dict = {}
|
||||
if self.force_values is not None:
|
||||
values = self.force_values
|
||||
else:
|
||||
values = self.client.get_creole()
|
||||
for varname, value in values.items():
|
||||
if varname in self.creole_variables_dict:
|
||||
# Creation of a slave create the master
|
||||
continue
|
||||
if varname.find('.') != -1:
|
||||
#support des groupes
|
||||
mastername, slavename = varname.split('.')
|
||||
if not mastername in self.creole_variables_dict or not \
|
||||
isinstance(self.creole_variables_dict [mastername],
|
||||
CreoleMaster):
|
||||
# Create the master variable
|
||||
if mastername in values:
|
||||
self.creole_variables_dict[mastername] = CreoleMaster(values[mastername])
|
||||
else:
|
||||
#only for CreoleLint
|
||||
self.creole_variables_dict[mastername] = CreoleMaster(value)
|
||||
#test only for CreoleLint
|
||||
if mastername != slavename:
|
||||
self.creole_variables_dict[mastername].add_slave(slavename, value)
|
||||
else:
|
||||
self.creole_variables_dict[varname] = value
|
||||
|
||||
def patch_template(self, filevar, force_no_active=False):
|
||||
"""Apply patch to a template
|
||||
"""
|
||||
var_dir = os.path.join(patch_dir,'variante')
|
||||
patch_cmd = ['patch', '-d', templatedir, '-N', '-p1']
|
||||
patch_no_debug = ['-s', '-r', '-', '--backup-if-mismatch']
|
||||
|
||||
tmpl_filename = os.path.split(filevar[u'source'])[1]
|
||||
# patches variante + locaux
|
||||
for directory in [var_dir, patch_dir]:
|
||||
patch_file = os.path.join(directory, '{0}.patch'.format(tmpl_filename))
|
||||
if os.access(patch_file, os.F_OK):
|
||||
msg = _(u"Patching template '{0}' with '{1}'")
|
||||
log.info(msg.format(filevar[u'source'], patch_file))
|
||||
ret, out, err = pyeole.process.system_out(patch_cmd + patch_no_debug + ['-i', patch_file])
|
||||
if ret != 0:
|
||||
msg = _(u"Error applying patch: '{0}'\nTo reproduce and fix this error {1}")
|
||||
log.error(msg.format(patch_file, ' '.join(patch_cmd + ['-i', patch_file])))
|
||||
#8307 : recopie le template original et n'arrête pas le processus
|
||||
self._copy_to_template_dir(filevar, force_no_active)
|
||||
#raise TemplateError(msg.format(patch_file, err))
|
||||
|
||||
def strip_template_comment(self, filevar):
|
||||
"""Strip comment from template
|
||||
|
||||
This apply if filevar has a del_comment attribut
|
||||
"""
|
||||
# suppression des commentaires si demandé (attribut del_comment)
|
||||
strip_cmd = ['sed', '-i']
|
||||
if u'del_comment' in filevar and filevar[u'del_comment'] != '':
|
||||
log.info(_(u"Cleaning file '{0}'").format( filevar[u'source'] ))
|
||||
ret, out, err = pyeole.process.system_out(strip_cmd
|
||||
+ ['/^\s*{0}/d ; /^$/d'.format(filevar[u'del_comment']),
|
||||
filevar[u'source'] ])
|
||||
if ret != 0:
|
||||
msg = _(u"Error removing comments '{0}': {1}")
|
||||
raise TemplateError(msg.format(filevar[u'del_comment'], err))
|
||||
|
||||
def _check_filevar(self, filevar, force_no_active=False):
|
||||
"""Verify that filevar is processable
|
||||
|
||||
:param filevar: template file informations
|
||||
:type filevar: `dict`
|
||||
|
||||
:raise CreoleClientError: if :data:`filevar` is disabled
|
||||
inexistant or unknown.
|
||||
|
||||
"""
|
||||
if not force_no_active and (u'activate' not in filevar or not filevar[u'activate']):
|
||||
|
||||
raise CreoleClientError(_(u"Template file not enabled:"
|
||||
u" {0}").format(basename(filevar[u'source'])))
|
||||
if u'source' not in filevar or filevar[u'source'] is None:
|
||||
raise CreoleClientError(_(u"Template file not set:"
|
||||
u" {0}").format(basename(filevar['source'])))
|
||||
|
||||
if u'name' not in filevar or filevar[u'name'] is None:
|
||||
raise CreoleClientError(_(u"Template target not set:"
|
||||
u" {0}").format(basename(filevar[u'source'])))
|
||||
|
||||
def _copy_to_template_dir(self, filevar, force_no_active=False):
|
||||
"""Copy template to processing temporary directory.
|
||||
|
||||
:param filevar: template file informations
|
||||
:type filevar: `dict`
|
||||
:param force_no_active: copy disabled template if `True`
|
||||
:type filevar: `bool`
|
||||
:raise FileNotFound: if source template does not exist
|
||||
|
||||
"""
|
||||
self._check_filevar(filevar, force_no_active)
|
||||
tmpl_source_name = os.path.split(filevar[u'source'])[1]
|
||||
tmpl_source_file = os.path.join(distrib_dir, tmpl_source_name)
|
||||
if not os.path.isfile(tmpl_source_file):
|
||||
msg = _(u"Template {0} unexistent").format(tmpl_source_file)
|
||||
raise FileNotFound(msg)
|
||||
else:
|
||||
log.info(_(u"Copy template: '{0}' -> '{1}'").format(tmpl_source_file, templatedir))
|
||||
shutil.copy(tmpl_source_file, templatedir)
|
||||
|
||||
def prepare_template(self, filevar, force_no_active=False):
|
||||
"""Prepare template source file
|
||||
"""
|
||||
self._copy_to_template_dir(filevar, force_no_active)
|
||||
self.patch_template(filevar, force_no_active)
|
||||
self.strip_template_comment(filevar)
|
||||
|
||||
def verify(self, filevar):
|
||||
"""
|
||||
verifie que les fichiers existent
|
||||
@param mkdir : création du répertoire si nécessaire
|
||||
"""
|
||||
if not os.path.isfile(filevar[u'source']):
|
||||
raise FileNotFound(_(u"File {0} does not exist.").format(filevar[u'source']))
|
||||
destfilename = filevar[u'full_name']
|
||||
dir_target = os.path.dirname(destfilename)
|
||||
if dir_target != '' and not os.path.isdir(dir_target):
|
||||
if not filevar[u'mkdir']:
|
||||
raise FileNotFound(_(u"Folder {0} does not exist but is required by {1}").format(dir_target, destfilename))
|
||||
os.makedirs(dir_target)
|
||||
# FIXME: pose plus de problème qu'autre chose (cf. #3048)
|
||||
#if not isfile(target):
|
||||
# system('cp %s %s' % (source, target))
|
||||
|
||||
def process(self, filevar, container):
|
||||
"""Process a cheetah template
|
||||
|
||||
Process a cheetah template and copy the file to destination.
|
||||
@param filevar: dictionary describing the file to process
|
||||
@type filevar: C{dict}
|
||||
@param container: dictionary describing the container
|
||||
@type container: C{dict}
|
||||
"""
|
||||
UTF = "#encoding: utf-8"
|
||||
|
||||
self._check_filevar(filevar)
|
||||
|
||||
# full path of the destination file
|
||||
destfilename = filevar[u'full_name']
|
||||
|
||||
log.info(_(u"Cheetah processing: '{0}' -> '{1}'").format(filevar[u'source'],
|
||||
destfilename))
|
||||
|
||||
# utilisation d'un fichier temporaire
|
||||
# afin de ne pas modifier l'original
|
||||
tmpfile = mktemp()
|
||||
shutil.copy(filevar[u'source'], tmpfile)
|
||||
|
||||
# ajout de l'en-tête pour le support de l'UTF-8
|
||||
# FIXME: autres encodages ?
|
||||
#os.system("sed -i '1i{0}' {1}".format(UTF, tmpfile)) (supprimé depuis #6224)
|
||||
|
||||
try:
|
||||
cheetah_template = CheetahTemplate(tmpfile, self.creole_variables_dict, container)
|
||||
os.unlink(tmpfile)
|
||||
# suppression de l'en-tête UTF-8 ajouté !!! (supprimé depuis #6224)
|
||||
data = str(cheetah_template) # .replace("{0}\n".format(UTF), '', 1)
|
||||
except CheetahNotFound, err:
|
||||
varname = err.args[0][13:-1]
|
||||
msg = _(u"Error: unknown variable used in template {0} : {1}").format(filevar[u'name'], varname)
|
||||
raise TemplateError, msg
|
||||
except UnicodeDecodeError, err:
|
||||
msg = _(u"Encoding issue detected in template {0}").format(filevar[u'name'])
|
||||
raise TemplateError, msg
|
||||
except Exception, err:
|
||||
msg = _(u"Error while instantiating template {0}: {1}").format(filevar[u'name'], err)
|
||||
raise TemplateError, msg
|
||||
|
||||
# écriture du fichier cible
|
||||
if destfilename == '':
|
||||
# CreoleCat may need to write on stdout (#10065)
|
||||
sys.stdout.write(data)
|
||||
else:
|
||||
try:
|
||||
file_h = file(destfilename, 'w')
|
||||
file_h.write(data)
|
||||
file_h.close()
|
||||
except IOError, e:
|
||||
msg = _(u"Unable to write in file '{0}': '{1}'").format(destfilename, e)
|
||||
raise FileNotFound, msg
|
||||
|
||||
def change_properties(self, filevar, container=None, force_full_name=False):
|
||||
chowncmd = [u'chown']
|
||||
chownarg = ''
|
||||
chmodcmd = [u'chmod']
|
||||
chmodarg = ''
|
||||
|
||||
if not force_full_name:
|
||||
destfilename = filevar[u'name']
|
||||
else:
|
||||
destfilename = filevar[u'full_name']
|
||||
|
||||
if u'owner' in filevar and filevar[u'owner']:
|
||||
chownarg = filevar[u'owner']
|
||||
else:
|
||||
chownarg = u'root'
|
||||
|
||||
if u'group' in filevar and filevar[u'group']:
|
||||
chownarg += ":" + filevar[u'group']
|
||||
else:
|
||||
chownarg += u':root'
|
||||
|
||||
if u'mode' in filevar and filevar[u'mode']:
|
||||
chmodarg = filevar[u'mode']
|
||||
else:
|
||||
chmodarg = u'0644'
|
||||
|
||||
chowncmd.extend( [chownarg, destfilename] )
|
||||
chmodcmd.extend( [chmodarg, destfilename] )
|
||||
|
||||
log.info(_(u'Changing properties: {0}').format(' '.join(chowncmd)) )
|
||||
ret, out, err = pyeole.process.creole_system_out( chowncmd, container=container, context=False )
|
||||
if ret != 0:
|
||||
log.error(_(u'Error changing properties {0}: {1}').format(ret, err) )
|
||||
|
||||
log.info(_(u'Changing properties: {0}').format(' '.join(chmodcmd)) )
|
||||
ret, out, err = pyeole.process.creole_system_out( chmodcmd, container=container, context=False )
|
||||
if ret != 0:
|
||||
log.error(_(u'Error changing properties {0}: {1}').format(ret, err) )
|
||||
|
||||
def remove_destfile(self, filevar):
|
||||
"""
|
||||
suppression du fichier de destination
|
||||
"""
|
||||
destfilename = filevar[u'full_name']
|
||||
if os.path.isfile(destfilename):
|
||||
os.unlink(destfilename)
|
||||
else:
|
||||
log.debug(_(u"File '{0}' unexistent.").format(destfilename))
|
||||
|
||||
|
||||
def _instance_file(self, filevar, container=None):
|
||||
"""Run templatisation on one file of one container
|
||||
|
||||
@param filevar: Dictionary describing the file
|
||||
@type filevar: C{dict}
|
||||
@param container: Dictionary describing a container
|
||||
@type container: C{dict}
|
||||
"""
|
||||
if not filevar.get(u'activate', False):
|
||||
try:
|
||||
# copy and patch disabled templates too (#11029)
|
||||
self.prepare_template(filevar, force_no_active=True)
|
||||
except FileNotFound:
|
||||
pass
|
||||
|
||||
if u'rm' in filevar and filevar[u'rm']:
|
||||
log.info(_(u"Removing file '{0}'"
|
||||
u" from container '{1}'").format(filevar[u'name'],
|
||||
container[u'name']))
|
||||
self.remove_destfile(filevar)
|
||||
|
||||
# The caller handles if it's an error
|
||||
raise TemplateDisabled(_(u"Instantiation of file '{0}' disabled").format(filevar[u'name']))
|
||||
|
||||
log.info(_(u"Instantiating file '{0}'"
|
||||
u" from '{1}'").format(filevar[u'name'], filevar[u'source']))
|
||||
self.prepare_template(filevar)
|
||||
self.verify(filevar)
|
||||
self.process(filevar, container)
|
||||
if filevar['name'].startswith('..') and container not in [None, 'root']:
|
||||
self.change_properties(filevar, None, True)
|
||||
else:
|
||||
self.change_properties(filevar, container)
|
||||
|
||||
|
||||
def instance_file(self, filename=None, container='root', ctx=None):
|
||||
"""Run templatisation on one file
|
||||
|
||||
@param filename: name of a file
|
||||
@type filename: C{str}
|
||||
@param container: name of a container
|
||||
@type container: C{str}
|
||||
"""
|
||||
if container == 'all':
|
||||
if ctx is None:
|
||||
groups = self.client.get_groups()
|
||||
else:
|
||||
groups = ctx.keys()
|
||||
for group in groups:
|
||||
if group in ['all', 'root']:
|
||||
continue
|
||||
if ctx is None:
|
||||
lctx = None
|
||||
else:
|
||||
lctx = ctx[group]
|
||||
self.instance_file(filename=filename, container=group, ctx=lctx)
|
||||
else:
|
||||
if ctx is None:
|
||||
ctx = self.client.get_container_infos(container)
|
||||
|
||||
filevars = [f for f in ctx[u'files'] if f[u'name'] == filename]
|
||||
for f in filevars:
|
||||
self._instance_file(f, ctx)
|
||||
|
||||
def instance_files(self, filenames=None, container=None, containers_ctx=None):
|
||||
"""Run templatisation on all files of all containers
|
||||
|
||||
@param filenames: names of files
|
||||
@type filename: C{list}
|
||||
@param container: name of a container
|
||||
@type container: C{str}
|
||||
"""
|
||||
if containers_ctx is None:
|
||||
containers_ctx = []
|
||||
if container is not None:
|
||||
containers_ctx = [self.client.get_container_infos(container)]
|
||||
else:
|
||||
for group_name in self.client.get_groups():
|
||||
containers_ctx.append(self.client.get_group_infos(group_name))
|
||||
if filenames is None:
|
||||
all_files = set(listdir(distrib_dir))
|
||||
prev_files = set(listdir(templatedir))
|
||||
all_declared_files = set()
|
||||
for ctx in containers_ctx:
|
||||
for fdict in ctx[u'files']:
|
||||
all_declared_files.add(basename(fdict['source']))
|
||||
undeclared_files = all_files - all_declared_files
|
||||
toremove_files = prev_files - all_files
|
||||
# delete old templates (#6600)
|
||||
for fname in toremove_files:
|
||||
rm_file = join(templatedir, fname)
|
||||
log.debug(_(u"Removing file '{0}'").format(rm_file))
|
||||
unlink(rm_file)
|
||||
# copy template not referenced in a dictionary (#6303)
|
||||
for fname in undeclared_files:
|
||||
fobj = {'source': join(templatedir, fname), 'name': ''}
|
||||
self.prepare_template(fobj, True)
|
||||
|
||||
for ctx in containers_ctx:
|
||||
for fdict in ctx[u'files']:
|
||||
if not filenames or fdict[u'name'] in filenames:
|
||||
try:
|
||||
self._instance_file(fdict, container=ctx)
|
||||
except TemplateDisabled, err:
|
||||
# Information on disabled template only useful
|
||||
# in debug
|
||||
log.debug(err, exc_info=True)
|
@ -1,26 +0,0 @@
|
||||
"""
|
||||
utilitaires créole
|
||||
"""
|
||||
import unicodedata
|
||||
|
||||
|
||||
# définition des classes d'adresse IP existantes
|
||||
def normalize_family(family_name, check_name=True):
|
||||
"""
|
||||
il ne faut pas d'espace, d'accent, de majuscule, de tiré, ...
|
||||
dans le nom des familles
|
||||
"""
|
||||
f = family_name
|
||||
f = f.replace('-', '_')
|
||||
#f = f.replace(u'é', 'e')
|
||||
#f = f.replace(u'è', 'e')
|
||||
nfkd_form = unicodedata.normalize('NFKD', f)
|
||||
f = u"".join([c for c in nfkd_form if not unicodedata.combining(c)])
|
||||
f = f.replace(' ', '_')
|
||||
f = f.lower()
|
||||
if f[0].isnumeric():
|
||||
raise ValueError(u'Le nom de la famille ne doit pas commencer par un chiffre : {0}'.format(f))
|
||||
if check_name and f == 'containers':
|
||||
raise ValueError(u'nom de la famille interdit {0}'.format(f))
|
||||
return f
|
||||
|
64
data/diag.py
64
data/diag.py
@ -1,64 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
###########################################################################
|
||||
# Eole NG - 2009
|
||||
# Copyright Pole de Competence Eole (Ministere Education - Academie Dijon)
|
||||
# http://eole.orion.education.fr - eole@ac-dijon.fr
|
||||
#
|
||||
# Licence CeCill
|
||||
# cf: http://www.cecill.info/licences.fr.html
|
||||
###########################################################################
|
||||
|
||||
import sys
|
||||
import socket
|
||||
from os.path import isfile
|
||||
from os import system, stat
|
||||
from pyeole.httprequest import HTTPRequest
|
||||
from creole.config import configeol
|
||||
from creole.client import CreoleClient
|
||||
|
||||
client = CreoleClient()
|
||||
|
||||
# adresse IP et port du serveur d'enregistrement
|
||||
server = "http://194.167.18.21/apps/AutoDiag/index.n/diagnose"
|
||||
md5file = "/etc/eole/.server.MD5"
|
||||
module = "%s-%s" % (client.get_creole('eole_module'), client.get_creole('eole_version'))
|
||||
|
||||
def get_md5():
|
||||
""" calcul de l'identifiant md5 """
|
||||
if not isfile(md5file) or stat(md5file).st_size == 0:
|
||||
system("md5sum %s | awk '{print $1}' > %s" % (configeol, md5file))
|
||||
fp = file(md5file)
|
||||
return (fp.read().split()[0])
|
||||
|
||||
def get_proxy():
|
||||
""" récupération du proxy à utiliser """
|
||||
if client.get_creole('activer_proxy_client') == 'oui':
|
||||
return "http://{0}:{1}".format(
|
||||
client.get_creole('proxy_client_adresse'),
|
||||
client.get_creole('proxy_client_port'))
|
||||
return ''
|
||||
|
||||
if __name__ == "__main__":
|
||||
id5 = get_md5()
|
||||
rne = client.get_creole('numero_etab')
|
||||
data = {"ID5":id5, "module":module, "rne":rne, "dep":rne[0:3]}
|
||||
socket.setdefaulttimeout(5)
|
||||
proxy = get_proxy()
|
||||
if proxy != '':
|
||||
# essai avec proxy
|
||||
try:
|
||||
req = HTTPRequest(proxy={'http':proxy})
|
||||
req.request(server, post_datas=data)
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
sys.exit(0)
|
||||
# essai sans proxy
|
||||
try:
|
||||
req = HTTPRequest()
|
||||
req.request(server, post_datas=data)
|
||||
except:
|
||||
sys.exit(1)
|
||||
else:
|
||||
sys.exit(0)
|
@ -1,2 +0,0 @@
|
||||
"""Module de fonctions supplémentaires accessibles à creole. Tous les fichiers python
|
||||
contenus dans ce répertoire sont lus par le module eosfunc de creole"""
|
@ -1,69 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: UTF-8 -*-
|
||||
"""
|
||||
script de generation d'un certificat ssl
|
||||
prend un nom de fichier facultatif en argument (destination du certificat)
|
||||
|
||||
usage::
|
||||
|
||||
soit
|
||||
%prog (-fc) [nom_certif]
|
||||
soit
|
||||
%prog (-f)
|
||||
|
||||
si [nom_certif] non renseigne, regenere tous les certificats par defaut ainsi que la ca locale.
|
||||
Sinon, ne genere que [nom_certif]
|
||||
|
||||
-f :force la regeneration du (ou des) certificat(s) s'il(s) existe(nt)
|
||||
-c : dans le cas de la generation d'un seul certificat, on copie la clef
|
||||
|
||||
"""
|
||||
import sys, os
|
||||
from optparse import OptionParser
|
||||
|
||||
from creole import cert
|
||||
from pyeole.encode import normalize
|
||||
|
||||
def parse_command_line():
|
||||
parser = OptionParser(__doc__)
|
||||
parser.add_option("-c",
|
||||
action="store_true", dest="copy", default=False,
|
||||
help="copie de la clef")
|
||||
|
||||
parser.add_option("-f",
|
||||
action="store_true", dest="regen", default=False,
|
||||
help="force la regeneration de la clef")
|
||||
|
||||
options, args = parser.parse_args()
|
||||
if len(args) > 1:
|
||||
parser.error("Il faut au maximum un certificat")
|
||||
return options, args
|
||||
|
||||
options, args = parse_command_line()
|
||||
|
||||
regen = options.regen
|
||||
copy = options.copy
|
||||
|
||||
if len(args) == 1:
|
||||
certfile = args[0]
|
||||
else:
|
||||
certfile = None
|
||||
|
||||
try:
|
||||
cert.rehash_if_needed()
|
||||
if certfile != None:
|
||||
certfile = os.path.abspath(certfile)
|
||||
dest_dir = os.path.dirname(certfile)
|
||||
if not os.path.isdir(dest_dir):
|
||||
print "Répertoire de destination inexistant (%s)" % dest_dir
|
||||
sys.exit(1)
|
||||
print "Generation du certificat machine"
|
||||
cert.gen_certif(certfile, regen=regen, copy_key=copy)
|
||||
else:
|
||||
# génération de tous les certificats (CA, eole, scribe...)
|
||||
cert.gen_certs(regen=regen)
|
||||
sys.exit(0)
|
||||
except Exception, err:
|
||||
print "Erreur : "
|
||||
print u'{0}'.format(normalize(err))
|
||||
sys.exit(1)
|
@ -1,26 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
# -*- coding: UTF-8 -*-
|
||||
"""
|
||||
Test des patches pour diagnose
|
||||
réutilisation du code de zephir-client
|
||||
"""
|
||||
import sys
|
||||
from glob import glob
|
||||
from os.path import basename
|
||||
from creole import utils
|
||||
from creole.config import patch_dir
|
||||
from zephir.monitor.agents import patches
|
||||
from os.path import join
|
||||
|
||||
patchs = glob(join(patch_dir, '*.patch'))
|
||||
patchs.extend(glob(join(patch_dir, 'variante', '*.patch')))
|
||||
err = []
|
||||
for patch in patchs:
|
||||
verif = patches.verify_patch(patch).values()
|
||||
if len(verif) > 0 and len(verif[0]) > 0:
|
||||
err.append(basename(patch))
|
||||
if len(err) != 0:
|
||||
utils.print_red('Erreur')
|
||||
print "fichiers : %s" % (", ".join(err),)
|
||||
else:
|
||||
utils.print_green('Ok')
|
200
eole.mk
200
eole.mk
@ -1,200 +0,0 @@
|
||||
#
|
||||
# NE PAS EDITER CE FICHIER
|
||||
#
|
||||
# Utiliser <appli>.mk à inclure à la fin de Makefile
|
||||
|
||||
#################
|
||||
# Sanity checks #
|
||||
#################
|
||||
|
||||
ifeq (, $(DESTDIR))
|
||||
$(warning $$(DESTDIR) is empty, installation will be done in /)
|
||||
endif
|
||||
|
||||
ifeq (, $(filter-out XXX-XXX, $(strip $(SOURCE))))
|
||||
$(error $$(SOURCE) variable has incorrect value '$(SOURCE)')
|
||||
endif
|
||||
|
||||
#########################
|
||||
# Variables definitions #
|
||||
#########################
|
||||
|
||||
INSTALL := install
|
||||
INSTALL_DATA := install -m 644
|
||||
INSTALL_PROGRAM := install -m 755
|
||||
INSTALL_DIRECTORY := install -m 755 -d
|
||||
INSTALL_RECURSIVE := cp -dr --no-preserve=ownership
|
||||
|
||||
# Base
|
||||
eole_DIR := $(DESTDIR)/usr/share/eole
|
||||
|
||||
ifeq ($(strip $(EOLE_VERSION)), 2.3)
|
||||
diagnose_PROG_DIR := $(eole_DIR)/diagnose/module
|
||||
else
|
||||
diagnose_PROG_DIR := $(eole_DIR)/diagnose/
|
||||
endif
|
||||
|
||||
# Creole
|
||||
creole_DIR := $(eole_DIR)/creole
|
||||
dicos_DATA_DIR := $(creole_DIR)/dicos
|
||||
tmpl_DATA_DIR := $(creole_DIR)/distrib
|
||||
pretemplate_PROG_DIR := $(eole_DIR)/pretemplate
|
||||
posttemplate_PROG_DIR := $(eole_DIR)/posttemplate
|
||||
postservice_PROG_DIR := $(eole_DIR)/postservice
|
||||
firewall_DATA_DIR := $(eole_DIR)/firewall
|
||||
bareos_restore_DATA_DIR := $(eole_DIR)/bareos/restore
|
||||
bareos_fichier_DATA_DIR := $(DESTDIR)/etc/bareos/bareosfichiers.d
|
||||
schedule_scripts_PROG_DIR := $(eole_DIR)/schedule/scripts
|
||||
extra_REC_DIR := $(creole_DIR)/extra
|
||||
|
||||
# Zéphir
|
||||
zephir_DATA_DIR := $(DESTDIR)/usr/share/zephir
|
||||
zephir_configs_DATA_DIR := $(zephir_DATA_DIR)/monitor/configs
|
||||
zephir_srv_DATA_DIR := $(zephir_configs_DATA_DIR)/services
|
||||
|
||||
# SSO
|
||||
sso_DATA_DIR := $(DESTDIR)/usr/share/sso
|
||||
sso_filtres_DATA_DIR := $(sso_DATA_DIR)/app_filters
|
||||
sso_user-info_DATA_DIR := $(sso_DATA_DIR)/user_infos
|
||||
|
||||
# EAD
|
||||
ead_DATA_DIR := $(DESTDIR)/usr/share/ead2/backend/config
|
||||
ead_actions_DATA_DIR := $(ead_DATA_DIR)/actions
|
||||
ead_perms_DATA_DIR := $(ead_DATA_DIR)/perms
|
||||
ead_roles_DATA_DIR := $(ead_DATA_DIR)/roles
|
||||
|
||||
# Program libraries goes under /usr/lib/<PROGRAM>/
|
||||
lib_$(SOURCE)_DATA_DIR := $(DESTDIR)/usr/lib/$(SOURCE)
|
||||
|
||||
# Scripts Eole
|
||||
scripts_PROG_DIR := $(eole_DIR)/sbin
|
||||
lib_eole_DATA_DIR := $(DESTDIR)/usr/lib/eole
|
||||
|
||||
# LDAP
|
||||
ldap_passwords_DATA_DIR := $(eole_DIR)/annuaire/password_files
|
||||
|
||||
# LXC
|
||||
lxc_DATA_DIR := $(eole_DIR)/lxc
|
||||
lxc_fstab_DATA_DIR := $(lxc_DATA_DIR)/fstab
|
||||
lxc_hosts_DATA_DIR := $(lxc_DATA_DIR)/hosts
|
||||
|
||||
# SQL
|
||||
sql_DATA_DIR := $(eole_DIR)/mysql/$(SOURCE)
|
||||
sql_gen_DATA_DIR := $(sql_DATA_DIR)/gen
|
||||
sql_updates_DATA_DIR := $(sql_DATA_DIR)/updates
|
||||
|
||||
sql_conf_gen_DATA_DIR := $(eole_DIR)/applications/gen
|
||||
sql_conf_passwords_DATA_DIR := $(eole_DIR)/applications/passwords
|
||||
sql_conf_updates_DATA_DIR := $(eole_DIR)/applications/updates/$(SOURCE)
|
||||
|
||||
# Certifs
|
||||
certs_DATA_DIR := $(eole_DIR)/certs
|
||||
|
||||
# Logrotate
|
||||
logrotate_DATA_DIR := $(DESTDIR)/etc/logrotate.d
|
||||
|
||||
|
||||
# Python modules
|
||||
ifneq ($(DESTDIR),)
|
||||
PYTHON_OPTS := --root $(DESTDIR)
|
||||
endif
|
||||
|
||||
# Translation
|
||||
TRANSLATION_SRC := translation
|
||||
TRANSLATION_DEST := $(DESTDIR)/usr/share/locale
|
||||
PO_FILES = $(wildcard $(TRANSLATION_SRC)/*/*.po)
|
||||
MO_FOLDERS = $(addprefix $(TRANSLATION_DEST), $(addsuffix LC_MESSAGES,$(subst $(TRANSLATION_SRC),,$(dir $(PO_FILES)))))
|
||||
|
||||
#############################################
|
||||
# Common directories and files installation #
|
||||
#############################################
|
||||
|
||||
all:
|
||||
|
||||
$(MO_FOLDERS):
|
||||
$(INSTALL_DIRECTORY) $@
|
||||
|
||||
$(PO_FILES): $(MO_FOLDERS)
|
||||
msgfmt -o $(TRANSLATION_DEST)$(subst $(TRANSLATION_SRC),,$(addsuffix LC_MESSAGES,$(dir $@)))/$(notdir $(@:.po=.mo)) $@
|
||||
|
||||
install-lang: $(PO_FILES)
|
||||
|
||||
install:: install-dirs install-files install-lang
|
||||
|
||||
# $1 = command to run
|
||||
# $2 = source directory
|
||||
# $3 = destination directory
|
||||
define fc_install_file
|
||||
if [ -d $2 ]; then \
|
||||
for file in `ls -1 $2/`; do \
|
||||
$1 $2/$$file $3 || true; \
|
||||
done; \
|
||||
fi
|
||||
endef
|
||||
|
||||
##
|
||||
## Directory creation
|
||||
##
|
||||
|
||||
# use % to catch local name in $*
|
||||
# data, program and recursive directory require a corresponding
|
||||
# directory in local sources
|
||||
%_DATA_DIR %_PROG_DIR %REC_DIR:
|
||||
test ! -d $(subst _,/,$*) || $(INSTALL_DIRECTORY) $($@)
|
||||
|
||||
# Create the directory referenced by the variable without a local one.
|
||||
%_DIR:
|
||||
$(INSTALL_DIRECTORY) $($@)
|
||||
|
||||
##
|
||||
## Install files present directly under data, program and recursive directories
|
||||
##
|
||||
|
||||
# $* : name of variable
|
||||
# $($*): value of variable
|
||||
%-instdata:
|
||||
$(call fc_install_file, $(INSTALL_DATA), $(subst _,/,$(subst _DATA_DIR,,$*)), $($*))
|
||||
|
||||
%-instprog:
|
||||
$(call fc_install_file, $(INSTALL_PROGRAM), $(subst _,/,$(subst _PROG_DIR,,$*)), $($*))
|
||||
|
||||
%-instrec:
|
||||
$(call fc_install_file, $(INSTALL_RECURSIVE), $(subst _,/,$(subst _REC_DIR,,$*)), $($*))
|
||||
|
||||
|
||||
# Use second expansion as variables may be created in included
|
||||
# Makefiles
|
||||
.SECONDEXPANSION:
|
||||
|
||||
# List of all directories
|
||||
installdirs_LIST = $(foreach V, $(filter %_DIR, $(.VARIABLES)), \
|
||||
$(if $(filter file, $(origin $(V))), \
|
||||
$(V)))
|
||||
# List of data directories
|
||||
installdata_LIST = $(filter %_DATA_DIR, $(installdirs_LIST))
|
||||
# List of program directories
|
||||
installprog_LIST = $(filter %_PROG_DIR, $(installdirs_LIST))
|
||||
# List of recursive directories
|
||||
installrec_LIST = $(filter %_REC_DIR, $(installdirs_LIST))
|
||||
|
||||
# Expand directories to create as dependency
|
||||
# Use double-colon to permit user to define additionnal install-dirs
|
||||
install-dirs:: $$(installdirs_LIST)
|
||||
|
||||
# Expand files to install as dependency
|
||||
# Use double-colon to permit user to define additionnal install-files
|
||||
install-files:: install-data-files install-prog-files install-rec-dirs
|
||||
|
||||
install-data-files: $$(patsubst %,%-instdata,$$(installdata_LIST))
|
||||
|
||||
install-prog-files: $$(patsubst %,%-instprog,$$(installprog_LIST))
|
||||
|
||||
install-rec-dirs: $$(patsubst %,%-instrec,$$(installrec_LIST))
|
||||
|
||||
# Installation of python modules
|
||||
ifeq ($(shell test -f setup.py && echo 0), 0)
|
||||
install-files::
|
||||
python3 setup.py install --no-compile --install-layout=deb $(PYTHON_OPTS)
|
||||
endif
|
||||
|
||||
.PHONY: install install-dirs install-files install-data-files install-prog-files install-rec-dirs
|
44
po_update.sh
44
po_update.sh
@ -1,44 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Création du fichier .pot et mise à jour des fichiers .po à partir des informations du fichier po_list
|
||||
if [[ -e po_list ]]; then
|
||||
while read p; do
|
||||
project=$(echo $p |awk '{print $1}')
|
||||
files=$(echo $p |cut -f 1 -d " " --complement)
|
||||
if [[ ! -d translation/fr ]]; then
|
||||
mkdir -p translation/fr
|
||||
fi
|
||||
if [[ ! -d translation/en ]]; then
|
||||
mkdir -p translation/en
|
||||
fi
|
||||
# Création des fichiers po minimum (fr et en) si nécessaire.
|
||||
xgettext -L Python --keyword=_:1,2 --from-code=UTF-8 --force-po -F --copyright-holder="projet EOLE" --package-name=$project --msgid-bugs-address=eole@ac-dijon.fr --foreign-user -d $project -o translation/$project.pot $files
|
||||
sed -i -e 's/\("Content-Type: text\/plain; charset=\).*\(\\n"\)/\1UTF-8\2/g' translation/$project.pot
|
||||
|
||||
# Mise à jour des fichiers po présents sous ./translation
|
||||
for po_file in $(find translation -name $project.po); do
|
||||
msgmerge -U $po_file translation/$project.pot
|
||||
done
|
||||
|
||||
if [[ ! -e translation/fr/${project}.po ]]; then
|
||||
msginit -i translation/${project}.pot -o translation/fr/${project}.po -l fr_FR
|
||||
sed -i -e "s/\\(\"PO-Revision-Date: \\).*\\(\\\\n\"\\)/\\1$(date '+%Y-%m-%d %H:%M%z')\\2/g" \
|
||||
-e 's/\("Language-Team: \).*\(\\n"\)/\1Équipe EOLE <eole@ac-dijon.fr>\2/g' \
|
||||
-e 's/\("Content-Type: text\/plain; charset=\).*\(\\n"\)/\1UTF-8\2/g' \
|
||||
translation/fr/${project}.po
|
||||
fi
|
||||
# Le fichier po "en" est écrasé.
|
||||
msgen -o translation/en/$project.po translation/$project.pot
|
||||
sed -i -e 's/\("Last-Translator: \).*\(\\n"\)/\1Équipe EOLE <eole@ac-dijon.fr>\2/g' \
|
||||
-e "s/\\(\"PO-Revision-Date: \\).*\\(\\\\n\"\\)/\\1$(date '+%Y-%m-%d %H:%M%z')\\2/g" \
|
||||
-e 's/\("Language-Team: \).*\(\\n"\)/\1Équipe EOLE <eole@ac-dijon.fr>\2/g' \
|
||||
-e 's/\("Language: \).*\(\\n"\)/\1en\2/g' \
|
||||
-e 's/\("Content-Type: text\/plain; charset=\).*\(\\n"\)/\1UTF-8\2/g' \
|
||||
-e 's/\("Plural-Forms: \).*/\1nplurals=2; plural=(n > 1);\\n"/' \
|
||||
-e '1,5 d' \
|
||||
translation/en/${project}.po
|
||||
|
||||
done < po_list
|
||||
fi
|
||||
|
||||
|
29
setup.py
29
setup.py
@ -1,24 +1,17 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from setuptools import setup
|
||||
import os, glob
|
||||
|
||||
BASE_DIR = 'share/'
|
||||
DOC_DIR = os.path.join(BASE_DIR, 'doc/creole')
|
||||
|
||||
# documentation
|
||||
doc = [(DOC_DIR, glob.glob('doc/*.html') + glob.glob('doc/*.txt')),
|
||||
(os.path.join(DOC_DIR, 'api'), glob.glob('doc/api/*.html') + glob.glob('doc/api/*.css')),
|
||||
]
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
setup(
|
||||
author='Équipe EOLE',
|
||||
author_email='eole@ac-dijon.fr',
|
||||
name='creole',
|
||||
version='2.7.0',
|
||||
description='Eole configuration tools',
|
||||
url='http://www.eole.orion.education.fr',
|
||||
packages=['creole', 'creole.lint', 'creole.valid'],
|
||||
data_files=doc
|
||||
author='Cadoles',
|
||||
author_email='contact@cadoles.com',
|
||||
name='rougail',
|
||||
version='0.1',
|
||||
description='Configuration templating engine',
|
||||
url='https://forge.cadoles.com/Infra/rougail',
|
||||
packages=find_packages('src'),
|
||||
package_dir={"": "src"},
|
||||
include_package_data=True,
|
||||
package_data={"": ["data/*.dtd"]}
|
||||
)
|
||||
|
5
src/rougail/__init__.py
Normal file
5
src/rougail/__init__.py
Normal file
@ -0,0 +1,5 @@
|
||||
from .loader import load
|
||||
from .objspace import CreoleObjSpace
|
||||
from .annotator import modes
|
||||
|
||||
__ALL__ = ('load', 'CreoleObjSpace', 'modes')
|
@ -53,18 +53,17 @@ modes = mode_factory()
|
||||
# that shall not be present in the exported (flatened) XML
|
||||
ERASED_ATTRIBUTES = ('redefine', 'exists', 'fallback', 'optional', 'remove_check', 'namespace',
|
||||
'remove_condition', 'path', 'instance_mode', 'index', 'is_in_leadership',
|
||||
'level') # , '_real_container')
|
||||
'level', 'submulti') # , '_real_container')
|
||||
ERASED_CONTAINER_ATTRIBUTES = ('id', 'container', 'group_id', 'group', 'container_group')
|
||||
|
||||
NOT_NEED_ACTIVATE = ('disknod',)
|
||||
|
||||
FORCE_CHOICE = {'oui/non': ['oui', 'non'],
|
||||
'on/off': ['on', 'off'],
|
||||
'yes/no': ['yes', 'no'],
|
||||
'schedule': ['none', 'daily', 'weekly', 'monthly'],
|
||||
'schedulemod': ['pre', 'post']}
|
||||
|
||||
KEY_TYPE = {'SymLinkOption': 'symlink',
|
||||
KEY_TYPE = {'variable': 'symlink',
|
||||
'SymLinkOption': 'symlink',
|
||||
'PortOption': 'port',
|
||||
'UnicodeOption': 'string',
|
||||
'NetworkOption': 'network',
|
||||
@ -72,20 +71,17 @@ KEY_TYPE = {'SymLinkOption': 'symlink',
|
||||
'URLOption': 'web_address',
|
||||
'FilenameOption': 'filename'}
|
||||
|
||||
TYPE_PARAM_CHECK = ('string', 'python', 'eole')
|
||||
TYPE_PARAM_CONDITION = ('string', 'python', 'number', 'eole')
|
||||
TYPE_PARAM_FILL = ('string', 'eole', 'number', 'context')
|
||||
|
||||
DISKNOD_KEY_TYPE = {'major': 'number',
|
||||
'minor': 'number'}
|
||||
TYPE_PARAM_CHECK = ('string', 'python', 'eole', 'variable')
|
||||
TYPE_PARAM_CONDITION = ('string', 'python', 'number', 'eole', 'variable')
|
||||
TYPE_PARAM_FILL = ('string', 'eole', 'number', 'context', 'variable')
|
||||
|
||||
ERASED_FAMILY_ACTION_ATTRIBUTES = ('index', 'action')
|
||||
|
||||
FREEZE_AUTOFREEZE_VARIABLE = 'module_instancie'
|
||||
|
||||
|
||||
class ContainerAnnotator:
|
||||
"""Manage container's object
|
||||
class ServiceAnnotator:
|
||||
"""Manage service's object
|
||||
"""
|
||||
def __init__(self, objectspace):
|
||||
self.space = objectspace.space
|
||||
@ -98,79 +94,99 @@ class ContainerAnnotator:
|
||||
</service_access>
|
||||
"""
|
||||
self.grouplist_conditions = {}
|
||||
self.convert_containers()
|
||||
self.convert_services()
|
||||
|
||||
def convert_containers(self):
|
||||
if hasattr(self.space, 'containers'):
|
||||
if hasattr(self.space.containers, 'container'):
|
||||
self.convert_all()
|
||||
def convert_services(self):
|
||||
if hasattr(self.space, 'services'):
|
||||
if hasattr(self.space.services, 'service'):
|
||||
subelts = dict()
|
||||
# self.space.containers.containers = self.objectspace.containers()
|
||||
for idx, container in enumerate(self.space.containers.container.values()):
|
||||
for idx, service in enumerate(self.space.services.service.values()):
|
||||
family = self.objectspace.family()
|
||||
family.name = 'container{}'.format(idx)
|
||||
family.doc = container.name
|
||||
family.name = 'service{}'.format(idx)
|
||||
family.doc = service.name
|
||||
family.family = OrderedDict()
|
||||
self.convert_container_to_family(family.name, family.family, container)
|
||||
setattr(self.space.containers, family.name, family)
|
||||
del self.space.containers.container
|
||||
self.convert_service_to_family(family.name, family.family, service)
|
||||
setattr(self.space.services, family.name, family)
|
||||
del self.space.services.service
|
||||
else:
|
||||
del self.space.containers
|
||||
del self.space.services
|
||||
|
||||
def convert_all(self):
|
||||
if hasattr(self.space.containers, 'all'):
|
||||
# Remove "all" and dispatch informations in all containers
|
||||
for type_, containers in vars(self.space.containers.all).items():
|
||||
if type_ == 'index':
|
||||
def convert_service_to_family(self, service_name, service_family, service):
|
||||
for elttype, values in vars(service).items():
|
||||
if elttype in ['name', 'index']:
|
||||
continue
|
||||
family = self.objectspace.family()
|
||||
family.name = elttype + 's'
|
||||
if isinstance(values, dict):
|
||||
values = list(values.values())
|
||||
family.family = self.convert_subelement_service(elttype,
|
||||
values,
|
||||
'services.{}.{}'.format(service_name, family.name))
|
||||
family.mode = None
|
||||
service_family[family.name] = family
|
||||
|
||||
def convert_subelement_service(self, name, elts, path):
|
||||
families = []
|
||||
new_elts = self._reorder_elts(name, elts, True)
|
||||
for index, elt_info in enumerate(new_elts):
|
||||
elt = elt_info['elt']
|
||||
elt_name = elt_info['elt_name']
|
||||
|
||||
# try to launch _update_xxxx() function
|
||||
update_elt = '_update_' + elt_name
|
||||
if hasattr(self, update_elt):
|
||||
getattr(self, update_elt)(elt, index, path)
|
||||
variables = []
|
||||
subpath = '{}.{}{}'.format(path, name, index)
|
||||
listname = '{}list'.format(name)
|
||||
activate_path = '.'.join([subpath, 'activate'])
|
||||
if elt in self.grouplist_conditions:
|
||||
# FIXME transformer le activate qui disparait en boolean
|
||||
self.objectspace.list_conditions.setdefault(listname,
|
||||
{}).setdefault(self.grouplist_conditions[elt],
|
||||
[]).append(activate_path)
|
||||
for key in dir(elt):
|
||||
if key.startswith('_') or key.endswith('_type') or key in ERASED_ATTRIBUTES:
|
||||
continue
|
||||
if isinstance(containers, list):
|
||||
for elt in containers:
|
||||
for container in self.space.containers.container.values():
|
||||
if container.name != 'all':
|
||||
if not hasattr(container, type_):
|
||||
setattr(container, type_, [])
|
||||
new_elt = copy(elt)
|
||||
new_elt.container = container
|
||||
getattr(container, type_).append(new_elt)
|
||||
value = getattr(elt, key)
|
||||
if isinstance(value, list):
|
||||
continue
|
||||
if key == 'service':
|
||||
value = value.name
|
||||
if key == listname:
|
||||
self.objectspace.list_conditions.setdefault(listname,
|
||||
{}).setdefault(
|
||||
value,
|
||||
[]).append(activate_path)
|
||||
continue
|
||||
if key == 'name':
|
||||
true_key = elt_name
|
||||
else:
|
||||
for name, elt in containers.items():
|
||||
for container in self.space.containers.container.values():
|
||||
if container.name != 'all':
|
||||
if not hasattr(container, type_):
|
||||
setattr(container, type_, OrderedDict())
|
||||
old_container = getattr(container, type_)
|
||||
if name in old_container:
|
||||
raise CreoleDictConsistencyError('{}'.format(name))
|
||||
new_elt = copy(elt)
|
||||
new_elt.container = container
|
||||
old_container[name] = new_elt
|
||||
del self.space.containers.all
|
||||
true_key = key
|
||||
if true_key in self.objectspace.booleans_attributs:
|
||||
type_ = 'boolean'
|
||||
else:
|
||||
type_ = 'string'
|
||||
dtd_key_type = true_key + '_type'
|
||||
|
||||
def convert_container_to_family(self, container_name, container_family, container):
|
||||
# tranform container object to family object
|
||||
# add services, service_accesses, ...
|
||||
for elttype in self.objectspace.container_elt_attr_list:
|
||||
if hasattr(container, elttype):
|
||||
family = self.objectspace.family()
|
||||
key_type_name = elttype.upper() + '_KEY_TYPE'
|
||||
if key_type_name in globals():
|
||||
key_type = globals()[key_type_name]
|
||||
else:
|
||||
key_type = {}
|
||||
if elttype.endswith('s'):
|
||||
family.name = elttype + 'es'
|
||||
else:
|
||||
family.name = elttype + 's'
|
||||
values = getattr(container, elttype)
|
||||
if isinstance(values, dict):
|
||||
values = list(values.values())
|
||||
family.family = self.make_group_from_elts(elttype,
|
||||
values,
|
||||
key_type,
|
||||
'containers.{}.{}'.format(container_name, family.name),
|
||||
True)
|
||||
family.mode = None
|
||||
container_family[family.name] = family
|
||||
if hasattr(elt, dtd_key_type):
|
||||
type_ = KEY_TYPE[getattr(elt, dtd_key_type)]
|
||||
multi = isinstance(value, list)
|
||||
variables.append(self._generate_element(elt_name,
|
||||
key,
|
||||
value,
|
||||
type_,
|
||||
subpath,
|
||||
multi))
|
||||
# FIXME ne devrait pas etre True par défaut
|
||||
variables.append(self._generate_element(name, 'activate', True, 'boolean', subpath))
|
||||
family = self.objectspace.family()
|
||||
family.name = '{}{}'.format(name, index)
|
||||
family.variable = variables
|
||||
family.mode = None
|
||||
self.paths.append('family', subpath, 'services', creoleobj=family)
|
||||
families.append(family)
|
||||
return families
|
||||
|
||||
def _generate_element(self, eltname, name, value, type_, subpath, multi=False):
|
||||
var_data = {'name': name, 'doc': '', 'value': value,
|
||||
@ -183,8 +199,7 @@ class ContainerAnnotator:
|
||||
var_data['type'] = type_
|
||||
|
||||
variable = self.objectspace.variable()
|
||||
if not HIGH_COMPATIBILITY:
|
||||
variable.mandatory = True
|
||||
variable.mandatory = True
|
||||
for key, value in var_data.items():
|
||||
if key == 'value':
|
||||
if value is None:
|
||||
@ -215,113 +230,27 @@ class ContainerAnnotator:
|
||||
choices.append(choice)
|
||||
variable.choice = choices
|
||||
path = '{}.{}'.format(subpath, name)
|
||||
self.paths.append('variable', path, 'containers', 'containers', variable)
|
||||
self.paths.append('variable', path, 'services', 'service', variable)
|
||||
return variable
|
||||
|
||||
def _make_disknod_auto(self, type_, index, variable, container_path):
|
||||
if not hasattr(self.space.constraints, 'auto'):
|
||||
self.space.constraints.auto = []
|
||||
auto = self.objectspace.auto()
|
||||
self.objectspace.index += 1
|
||||
auto.index = self.objectspace.index
|
||||
auto.namespace = 'containers'
|
||||
param1 = self.objectspace.param()
|
||||
param1.text = type_
|
||||
param2 = self.objectspace.param()
|
||||
param2.text = variable.name
|
||||
auto.param = [param1, param2]
|
||||
auto.name = 'cdrom_minormajor'
|
||||
family = 'disknod{}'.format(index)
|
||||
auto.target = '{}.{}.{}'.format(container_path, family, type_)
|
||||
if not hasattr(self.space, 'constraints'):
|
||||
self.space.constraints = self.objectspace.constraints()
|
||||
self.space.constraints.auto.append(auto)
|
||||
|
||||
def _make_disknod_type(self, index, variable, container_path):
|
||||
auto = self.objectspace.auto()
|
||||
self.objectspace.index += 1
|
||||
auto.index = self.objectspace.index
|
||||
auto.namespace = 'containers'
|
||||
param = self.objectspace.param()
|
||||
param.text = variable.name
|
||||
auto.param = [param]
|
||||
auto.name = 'device_type'
|
||||
family = 'disknod{}'.format(index)
|
||||
auto.target = '{}.{}.type'.format(container_path, family)
|
||||
if not hasattr(self.space, 'constraints'):
|
||||
self.space.constraints = self.objectspace.constraints()
|
||||
if not hasattr(self.space.constraints, 'auto'):
|
||||
self.space.constraints.auto = []
|
||||
self.space.constraints.auto.append(auto)
|
||||
|
||||
|
||||
def _update_disknod(self, disknod, index, container_path):
|
||||
disknod.major = None
|
||||
disknod.minor = None
|
||||
disknod.type = None
|
||||
self._make_disknod_auto('minor', index, disknod, container_path)
|
||||
self._make_disknod_auto('major', index, disknod, container_path)
|
||||
self._make_disknod_type(index, disknod, container_path)
|
||||
disknod.mode = u'rwm'
|
||||
disknod.permission = 'allow'
|
||||
|
||||
def _update_file(self, file_, index, container_path):
|
||||
if not hasattr(file_, 'source'):
|
||||
file_.source = basename(file_.name)
|
||||
|
||||
def _split_elts(self, name, key, value, elt):
|
||||
"""for example::
|
||||
|
||||
<service_access service='ntp'>
|
||||
<port protocol='udp' service_accesslist='ntp_udp'>123</port>
|
||||
<tcpwrapper>ntpd</tcpwrapper>
|
||||
</service_access>
|
||||
|
||||
builds a `service_access` object, but we need **two** objects `service_access`,
|
||||
for example one for the port and one for the tcpwrapper
|
||||
"""
|
||||
for subelt in value:
|
||||
new_elt = copy(elt)
|
||||
for subsubelt in dir(subelt):
|
||||
if subsubelt.startswith('_') or subsubelt == 'index':
|
||||
continue
|
||||
if hasattr(new_elt, subsubelt):
|
||||
if hasattr(elt, 'name'):
|
||||
name_ = elt.name
|
||||
else:
|
||||
name_ = elt.service
|
||||
raise CreoleDictConsistencyError(_('attribute {} already exists '
|
||||
'for {}').format(subsubelt,
|
||||
name_))
|
||||
setattr(new_elt, subsubelt, getattr(subelt, subsubelt))
|
||||
if hasattr(new_elt, 'node_name') or hasattr(new_elt, 'name_type'):
|
||||
raise CreoleDictConsistencyError(_('attribute node_name or name_type '
|
||||
'already exists for {}'
|
||||
'').format(name))
|
||||
if hasattr(subelt, key + '_type'):
|
||||
type_ = getattr(subelt, key + '_type')
|
||||
setattr(new_elt, 'name_type', type_)
|
||||
setattr(new_elt, 'node_name', key)
|
||||
if not hasattr(new_elt, name + 'list'):
|
||||
setattr(new_elt, name + 'list', '___auto_{}'.format(elt.service))
|
||||
else:
|
||||
self.grouplist_conditions[new_elt] = '___auto_{}'.format(elt.service)
|
||||
yield new_elt
|
||||
def _update_file(self, file_, index, service_path):
|
||||
if file_.file_type == "UnicodeOption":
|
||||
if not hasattr(file_, 'source'):
|
||||
file_.source = basename(file_.name)
|
||||
elif not hasattr(file_, 'source'):
|
||||
raise CreoleDictConsistencyError(_('attribute source mandatory for file with variable name '
|
||||
'for {}').format(file_.name))
|
||||
|
||||
def _reorder_elts(self, name, elts, duplicate_list):
|
||||
"""Reorders by index the elts (the interface,
|
||||
the hosts, actions...)
|
||||
"""Reorders by index the elts
|
||||
"""
|
||||
dict_elts = OrderedDict()
|
||||
# reorder elts by index
|
||||
new_elts = {}
|
||||
not_indexed = []
|
||||
for elt in elts:
|
||||
if not hasattr(elt, 'index'):
|
||||
not_indexed.append(elt)
|
||||
else:
|
||||
idx = elt.index
|
||||
new_elts.setdefault(idx, []).append(elt)
|
||||
idx = elt.index
|
||||
new_elts.setdefault(idx, []).append(elt)
|
||||
idxes = list(new_elts.keys())
|
||||
idxes.sort()
|
||||
elts = not_indexed
|
||||
@ -333,16 +262,8 @@ class ContainerAnnotator:
|
||||
if key.startswith('_') or key.endswith('_type') or key in ERASED_ATTRIBUTES:
|
||||
continue
|
||||
value = getattr(elt, key)
|
||||
if isinstance(value, list) and duplicate_list:
|
||||
for new_elt in self._split_elts(name, key, value, elt):
|
||||
dict_elts.setdefault(new_elt.name, []).append({'elt_name': key,
|
||||
'elt': new_elt})
|
||||
elt_added = True
|
||||
if not elt_added:
|
||||
if hasattr(elt, 'name'):
|
||||
eltname = elt.name
|
||||
else:
|
||||
eltname = idx
|
||||
eltname = elt.name
|
||||
dict_elts.setdefault(eltname, []).append({'elt_name': name, 'elt': elt})
|
||||
|
||||
result_elts = []
|
||||
@ -350,7 +271,7 @@ class ContainerAnnotator:
|
||||
result_elts.extend(elt)
|
||||
return result_elts
|
||||
|
||||
def make_group_from_elts(self, name, elts, key_type, path, duplicate_list):
|
||||
def make_group_from_elts(self, name, elts, path, duplicate_list):
|
||||
"""Splits each objects into a group (and `OptionDescription`, in tiramisu terms)
|
||||
and build elements and its attributes (the `Options` in tiramisu terms)
|
||||
"""
|
||||
@ -368,7 +289,7 @@ class ContainerAnnotator:
|
||||
subpath = '{}.{}{}'.format(path, name, index)
|
||||
listname = '{}list'.format(name)
|
||||
activate_path = '.'.join([subpath, 'activate'])
|
||||
if name not in NOT_NEED_ACTIVATE and elt in self.grouplist_conditions:
|
||||
if elt in self.grouplist_conditions:
|
||||
# FIXME transformer le activate qui disparait en boolean
|
||||
self.objectspace.list_conditions.setdefault(listname,
|
||||
{}).setdefault(self.grouplist_conditions[elt],
|
||||
@ -378,19 +299,18 @@ class ContainerAnnotator:
|
||||
continue
|
||||
value = getattr(elt, key)
|
||||
if isinstance(value, list) and duplicate_list:
|
||||
# FIXME plusieurs fichier si calculé !
|
||||
continue
|
||||
if key == 'container':
|
||||
value = value.name
|
||||
if name not in NOT_NEED_ACTIVATE and key == listname:
|
||||
if key == listname:
|
||||
self.objectspace.list_conditions.setdefault(listname,
|
||||
{}).setdefault(
|
||||
value,
|
||||
[]).append(activate_path)
|
||||
continue
|
||||
default_type = 'string'
|
||||
if key in self.objectspace.booleans_attributs:
|
||||
default_type = 'boolean'
|
||||
type_ = key_type.get(key, default_type)
|
||||
type_ = 'boolean'
|
||||
else:
|
||||
type_ = 'string'
|
||||
dtd_key_type = key + '_type'
|
||||
if hasattr(elt, dtd_key_type):
|
||||
type_ = KEY_TYPE[getattr(elt, dtd_key_type)]
|
||||
@ -401,19 +321,18 @@ class ContainerAnnotator:
|
||||
type_,
|
||||
subpath,
|
||||
multi))
|
||||
if name not in NOT_NEED_ACTIVATE:
|
||||
# FIXME ne devrait pas etre True par défaut
|
||||
variables.append(self._generate_element(name, 'activate', True, 'boolean', subpath))
|
||||
# FIXME ne devrait pas etre True par défaut
|
||||
variables.append(self._generate_element(name, 'activate', True, 'boolean', subpath))
|
||||
family = self.objectspace.family()
|
||||
family.name = '{}{}'.format(name, index)
|
||||
family.variable = variables
|
||||
family.mode = None
|
||||
self.paths.append('family', subpath, 'containers', creoleobj=family)
|
||||
self.paths.append('family', subpath, 'services', creoleobj=family)
|
||||
families.append(family)
|
||||
return families
|
||||
|
||||
|
||||
class ActionAnnotator(ContainerAnnotator):
|
||||
class ActionAnnotator(ServiceAnnotator):
|
||||
def __init__(self, objectspace):
|
||||
self.space = objectspace.space
|
||||
self.paths = objectspace.paths
|
||||
@ -438,7 +357,7 @@ class ActionAnnotator(ContainerAnnotator):
|
||||
'').format(namespace))
|
||||
namespaces.append(namespace)
|
||||
action.name = action.namespace
|
||||
new_actions = self.make_group_from_elts('action', actions.action, {}, subpath, False)
|
||||
new_actions = self.make_group_from_elts('action', actions.action, subpath, False)
|
||||
family = self.objectspace.family()
|
||||
family.name = actions.name
|
||||
family.family = new_actions
|
||||
@ -465,7 +384,7 @@ class SpaceAnnotator(object):
|
||||
self.has_calc = []
|
||||
self.force_no_value = []
|
||||
self.force_not_mandatory = []
|
||||
if eosfunc_file is not None:
|
||||
if eosfunc_file:
|
||||
self.eosfunc = imp.load_source('eosfunc', eosfunc_file)
|
||||
else:
|
||||
self.eosfunc = None
|
||||
@ -473,6 +392,7 @@ class SpaceAnnotator(object):
|
||||
self.default_has_no_value = []
|
||||
self.has_frozen_if_in_condition = []
|
||||
self.default_variable_options()
|
||||
self.variable_submulti()
|
||||
self.convert_auto_freeze()
|
||||
self.convert_groups()
|
||||
self.filter_check()
|
||||
@ -483,8 +403,9 @@ class SpaceAnnotator(object):
|
||||
self.remove_empty_families()
|
||||
self.change_variable_mode()
|
||||
self.change_family_mode()
|
||||
self.dynamic_families()
|
||||
self.filter_separators()
|
||||
self.absolute_path_for_symlink_in_containers()
|
||||
self.absolute_path_for_symlink_in_services()
|
||||
self.convert_helps()
|
||||
if hasattr(self.space, 'constraints'):
|
||||
del self.space.constraints.index
|
||||
@ -492,10 +413,10 @@ class SpaceAnnotator(object):
|
||||
raise Exception('constraints again?')
|
||||
del self.space.constraints
|
||||
|
||||
def absolute_path_for_symlink_in_containers(self):
|
||||
if not hasattr(self.space, 'containers'):
|
||||
def absolute_path_for_symlink_in_services(self):
|
||||
if not hasattr(self.space, 'services'):
|
||||
return
|
||||
families = vars(self.space.containers).values()
|
||||
families = vars(self.space.services).values()
|
||||
for family in families:
|
||||
if hasattr(family, 'family'):
|
||||
for fam in family.family.values():
|
||||
@ -541,8 +462,8 @@ class SpaceAnnotator(object):
|
||||
if is_leader:
|
||||
if variable.name == follower_names[0]:
|
||||
# followers are multi
|
||||
if not variable.multi is True:
|
||||
raise CreoleDictConsistencyError(_('the variable {} in a group must be multi').format(variable.name))
|
||||
if not variable.multi:
|
||||
raise CreoleDictConsistencyError(_('the variable {} in a group must be multi or submulti').format(variable.name))
|
||||
follower_names.remove(variable.name)
|
||||
leader_family.variable.pop(variable.name)
|
||||
leader_space.variable.append(variable) # pylint: disable=E1101
|
||||
@ -560,6 +481,10 @@ class SpaceAnnotator(object):
|
||||
leader_space.variable = []
|
||||
leader_space.name = leader_name
|
||||
leader_space.hidden = variable.hidden
|
||||
if hasattr(group, 'description'):
|
||||
leader_space.doc = group.description
|
||||
else:
|
||||
leader_space.doc = variable.description
|
||||
variable.hidden = None
|
||||
self.paths.append('family', leader_path + '.' + leader_name, namespace, creoleobj=leader_space)
|
||||
# manage leader's variable
|
||||
@ -606,10 +531,18 @@ class SpaceAnnotator(object):
|
||||
variable_mode = variable.mode
|
||||
if variable_mode is not None and modes[mode] > modes[variable_mode]:
|
||||
mode = variable_mode
|
||||
if family.name == 'Containers':
|
||||
family.mode = 'normal'
|
||||
else:
|
||||
family.mode = mode
|
||||
family.mode = mode
|
||||
|
||||
def dynamic_families(self): # pylint: disable=C0111
|
||||
if not hasattr(self.space, 'variables'):
|
||||
return
|
||||
for family in self.space.variables.values():
|
||||
if hasattr(family, 'family'):
|
||||
for family in family.family.values():
|
||||
if 'dynamic' in vars(family):
|
||||
namespace = self.paths.get_variable_namespace(family.dynamic)
|
||||
varpath = self.paths.get_variable_path(family.dynamic, namespace)
|
||||
family.dynamic = varpath
|
||||
|
||||
def _annotate_variable(self, variable, family_mode, path, is_follower=False):
|
||||
if (HIGH_COMPATIBILITY and variable.type == 'choice' and variable.mode != modes_level[-1] and variable.mandatory is True and path in self.default_has_no_value):
|
||||
@ -623,7 +556,7 @@ class SpaceAnnotator(object):
|
||||
(not has_value or is_follower) and variable.type != 'choice'):
|
||||
variable.mode = modes_level[0]
|
||||
if has_value:
|
||||
if not HIGH_COMPATIBILITY or (not path.startswith('creole.containers.') \
|
||||
if not HIGH_COMPATIBILITY or (not path.startswith('creole.services.') \
|
||||
and path not in self.force_no_value and path not in self.force_not_mandatory):
|
||||
variable.mandatory = True
|
||||
if variable.hidden is True:
|
||||
@ -636,8 +569,6 @@ class SpaceAnnotator(object):
|
||||
variable.mode = family_mode
|
||||
if variable.mode != None and variable.mode != modes_level[0] and modes[variable.mode] < modes[family_mode]:
|
||||
variable.mode = family_mode
|
||||
if variable.name == "available_probes":
|
||||
variable.force_default_on_freeze = False
|
||||
|
||||
def default_variable_options(self):
|
||||
if hasattr(self.space, 'variables'):
|
||||
@ -651,6 +582,16 @@ class SpaceAnnotator(object):
|
||||
if variable.type != 'symlink' and not hasattr(variable, 'description'):
|
||||
variable.description = variable.name
|
||||
|
||||
def variable_submulti(self):
|
||||
if hasattr(self.space, 'variables'):
|
||||
for families in self.space.variables.values():
|
||||
if hasattr(families, 'family'):
|
||||
for family in families.family.values():
|
||||
if hasattr(family, 'variable'):
|
||||
for variable in family.variable.values():
|
||||
if variable.submulti:
|
||||
variable.multi = 'submulti'
|
||||
|
||||
def convert_auto_freeze(self): # pylint: disable=C0111
|
||||
if hasattr(self.space, 'variables'):
|
||||
for variables in self.space.variables.values():
|
||||
@ -768,19 +709,9 @@ class SpaceAnnotator(object):
|
||||
is_follower = False
|
||||
path = '{}.{}.{}'.format(family.path, variable.name, follower.name)
|
||||
self._annotate_variable(follower, family_mode, path, is_follower)
|
||||
if HIGH_COMPATIBILITY:
|
||||
# leader's variable are right
|
||||
if modes[variable.variable[0].mode] > modes[follower.mode]:
|
||||
follower.mode = variable.variable[0].mode
|
||||
else:
|
||||
# auto_save's variable is set in 'basic' mode if its mode is 'normal'
|
||||
if follower.auto_save is True and follower.mode != modes_level[-1]:
|
||||
follower.mode = modes_level[0]
|
||||
if modes[mode] > modes[follower.mode]:
|
||||
mode = follower.mode
|
||||
if not HIGH_COMPATIBILITY:
|
||||
# the leader's mode is the lowest
|
||||
variable.variable[0].mode = mode
|
||||
# leader's mode is minimum level
|
||||
if modes[variable.variable[0].mode] > modes[follower.mode]:
|
||||
follower.mode = variable.variable[0].mode
|
||||
variable.mode = variable.variable[0].mode
|
||||
else:
|
||||
# auto_save's variable is set in 'basic' mode if its mode is 'normal'
|
||||
@ -811,13 +742,9 @@ class SpaceAnnotator(object):
|
||||
# sort fill/auto by index
|
||||
if 'fill' in vars(constraints):
|
||||
for idx, fill in enumerate(constraints.fill):
|
||||
if fill.index in fills:
|
||||
raise Exception('hu?')
|
||||
fills[fill.index] = {'idx': idx, 'fill': fill, 'type': 'fill'}
|
||||
if 'auto' in vars(constraints):
|
||||
for idx, fill in enumerate(constraints.auto):
|
||||
if fill.index in fills:
|
||||
raise Exception('hu?')
|
||||
fills[fill.index] = {'idx': idx, 'fill': fill, 'type': 'auto'}
|
||||
indexes = list(fills.keys())
|
||||
indexes.sort()
|
||||
@ -826,10 +753,7 @@ class SpaceAnnotator(object):
|
||||
remove_fills = []
|
||||
for idx in indexes:
|
||||
fill = fills[idx]['fill']
|
||||
if hasattr(fill, 'redefine'):
|
||||
redefine = bool(fill.redefine)
|
||||
else:
|
||||
redefine = False
|
||||
redefine = bool(fill.redefine)
|
||||
if fill.target in targets:
|
||||
if redefine:
|
||||
if targets[fill.target][1] == 'auto':
|
||||
@ -931,9 +855,11 @@ class SpaceAnnotator(object):
|
||||
if param.type not in TYPE_PARAM_CHECK:
|
||||
raise CreoleDictConsistencyError(_('cannot use {} type as a param in check for {}').format(param.type, check.target))
|
||||
if param.type == 'eole':
|
||||
if HIGH_COMPATIBILITY and param.text.startswith('container_ip'):
|
||||
if param.optional is True:
|
||||
param_option_indexes.append(idx)
|
||||
param.type = 'variable'
|
||||
if param.type == 'variable':
|
||||
# if HIGH_COMPATIBILITY and param.text.startswith('container_ip'):
|
||||
# if param.optional is True:
|
||||
# param_option_indexes.append(idx)
|
||||
try:
|
||||
param.text = self.paths.get_variable_path(param.text, namespace)
|
||||
except CreoleDictConsistencyError as err:
|
||||
@ -981,8 +907,10 @@ class SpaceAnnotator(object):
|
||||
for idx in remove_indexes:
|
||||
del space[idx]
|
||||
remove_indexes = []
|
||||
functions = dir(self.eosfunc)
|
||||
functions.extend(['valid_enum', 'valid_in_network', 'valid_differ'])
|
||||
for idx, check in enumerate(space):
|
||||
if not check.name in dir(self.eosfunc):
|
||||
if not check.name in functions:
|
||||
raise CreoleDictConsistencyError(_('cannot find check function {}').format(check.name))
|
||||
#is_probe = not check.name in self.eosfunc.func_on_zephir_context
|
||||
#if is_probe:
|
||||
@ -1009,7 +937,7 @@ class SpaceAnnotator(object):
|
||||
'').format(check.target))
|
||||
param = check.param[0]
|
||||
if proposed_value_type:
|
||||
if param.type != 'eole':
|
||||
if param.type == 'variable':
|
||||
try:
|
||||
values = self.load_params_in_validenum(param)
|
||||
except NameError as err:
|
||||
@ -1059,20 +987,20 @@ class SpaceAnnotator(object):
|
||||
elif name == 'valid_network_netmask':
|
||||
params_len = 1
|
||||
if len(check.param) != params_len:
|
||||
raise CreoleLoaderError(_('{} must have {} param').format(name, params_len))
|
||||
raise CreoleDictConsistencyError(_('{} must have {} param').format(name, params_len))
|
||||
elif name == 'valid_ipnetmask':
|
||||
params_len = 1
|
||||
if len(check.param) != params_len:
|
||||
raise CreoleLoaderError(_('{} must have {} param').format(name, params_len))
|
||||
raise CreoleDictConsistencyError(_('{} must have {} param').format(name, params_len))
|
||||
name = 'valid_ip_netmask'
|
||||
elif name == 'valid_broadcast':
|
||||
params_len = 2
|
||||
if len(check.param) != params_len:
|
||||
raise CreoleLoaderError(_('{} must have {} param').format(name, params_len))
|
||||
raise CreoleDictConsistencyError(_('{} must have {} param').format(name, params_len))
|
||||
elif name == 'valid_in_network':
|
||||
params_len = 2
|
||||
if len(check.param) != params_len:
|
||||
raise CreoleLoaderError(_('{} must have {} param').format(name, params_len))
|
||||
raise CreoleDictConsistencyError(_('{} must have {} param').format(name, params_len))
|
||||
check_.name = name
|
||||
check_.warnings_only = check.warnings_only
|
||||
if hasattr(check, 'param'):
|
||||
@ -1108,12 +1036,13 @@ class SpaceAnnotator(object):
|
||||
if param.type not in TYPE_PARAM_FILL:
|
||||
raise CreoleDictConsistencyError(_('cannot use {} type as a param '
|
||||
'in a fill/auto').format(param.type))
|
||||
if param.type == 'eole':
|
||||
param.type = 'variable'
|
||||
param_option_indexes = []
|
||||
for fill_idx, param in enumerate(fill.param):
|
||||
if not hasattr(param, 'text') and \
|
||||
(param.type == 'eole' or param.type == 'number' or \
|
||||
#param.type == 'container' or param.type == 'python'):
|
||||
param.type == 'python'):
|
||||
(param.type == 'variable' or param.type == 'number' or \
|
||||
param.type == 'python'):
|
||||
raise CreoleDictConsistencyError(_("All '{}' variables shall be set in "
|
||||
"order to calculate {}").format(
|
||||
param.type,
|
||||
@ -1121,16 +1050,16 @@ class SpaceAnnotator(object):
|
||||
# if param.type == 'container':
|
||||
# param.type = 'eole'
|
||||
# param.text = 'container_ip_{}'.format(param.text)
|
||||
if param.type == 'eole':
|
||||
if param.type == 'variable':
|
||||
#if is_probe:
|
||||
# raise CreoleDictConsistencyError(_('Function {0} used to calculate {1} '
|
||||
# 'is executed on remote server, '
|
||||
# 'so cannot depends to an '
|
||||
# 'other variable'
|
||||
# ).format(fill.name, fill.target))
|
||||
if HIGH_COMPATIBILITY and param.text.startswith('container_ip'):
|
||||
if param.optional is True:
|
||||
param_option_indexes.append(fill_idx)
|
||||
# if HIGH_COMPATIBILITY and param.text.startswith('container_ip'):
|
||||
# if param.optional is True:
|
||||
# param_option_indexes.append(fill_idx)
|
||||
try:
|
||||
param.text = self.paths.get_variable_path(param.text, namespace)
|
||||
except CreoleDictConsistencyError as err:
|
||||
@ -1313,6 +1242,8 @@ class SpaceAnnotator(object):
|
||||
if param.type not in TYPE_PARAM_CONDITION:
|
||||
raise CreoleDictConsistencyError(_('cannot use {} type as a param '
|
||||
'in a condition').format(param.type))
|
||||
if param.type == 'eole':
|
||||
param.type = 'variable'
|
||||
|
||||
def check_choice_option_condition(self, force_remove_targets):
|
||||
# remove condition for ChoiceOption that don't have param
|
17
src/rougail/config.py
Normal file
17
src/rougail/config.py
Normal file
@ -0,0 +1,17 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
fichier de configuration pour rougail
|
||||
|
||||
"""
|
||||
from os.path import join, isfile, abspath, dirname
|
||||
from pathlib import Path
|
||||
|
||||
rougailroot = '/var/rougail'
|
||||
patch_dir = join(rougailroot, 'patches')
|
||||
manifests_dir = join(rougailroot, 'manifests')
|
||||
templates_dir = join(rougailroot, 'templates')
|
||||
dtddir = join(dirname(abspath(__file__)), 'data')
|
||||
dtdfilename = join(dtddir, 'rougail.dtd')
|
||||
|
||||
# chemin du répertoire source des fichiers templates
|
||||
patch_dir = '/srv/rougail/patch'
|
@ -2,20 +2,20 @@
|
||||
|
||||
<!-- ===================================================================== -->
|
||||
|
||||
<!-- Definition de la DTD du fichier creole -->
|
||||
<!-- Rougail's DTD -->
|
||||
|
||||
<!-- ===================================================================== -->
|
||||
|
||||
<!--
|
||||
# Conception :
|
||||
# Eole (http://eole.orion.education.fr)
|
||||
|
||||
# Created by:
|
||||
# EOLE (http://eole.orion.education.fr)
|
||||
# Copyright (C) 2005-2018
|
||||
|
||||
# distribue sous la licence GPL-2
|
||||
# Forked by:
|
||||
# Cadoles (http://www.cadoles.com)
|
||||
# Copyright (C) 2019
|
||||
|
||||
# En attendant une traduction officielle de la GPL, la notice de
|
||||
# copyright demeure en anglais.
|
||||
# distribued with GPL-2 or later license
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -30,15 +30,14 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
# Se reporter a la documentation envoyee avec le programme pour la notice.
|
||||
|
||||
-->
|
||||
|
||||
|
||||
<!--================ -->
|
||||
<!-- root element -->
|
||||
<!-- =============== -->
|
||||
|
||||
<!ELEMENT creole (containers | family_action | variables | constraints | help)*>
|
||||
<!ELEMENT rougail (services | family_action | variables | constraints | help)*>
|
||||
|
||||
<!-- ============== -->
|
||||
<!-- files element -->
|
||||
@ -58,26 +57,18 @@
|
||||
<!ATTLIST action actionlist CDATA #IMPLIED>
|
||||
<!-- for apache action -->
|
||||
<!ATTLIST action apache_path CDATA #IMPLIED>
|
||||
<!ATTLIST action apache_path_type (FilenameOption|SymLinkOption) "FilenameOption">
|
||||
<!ATTLIST action apache_path_type (FilenameOption|SymLinkOption|variable) "FilenameOption">
|
||||
<!-- for external action -->
|
||||
<!ATTLIST action url CDATA #IMPLIED>
|
||||
<!ATTLIST action url_type (URLOption|SymLinkOption) "URLOption">
|
||||
<!ATTLIST action url_type (URLOption|SymLinkOption|variable) "URLOption">
|
||||
<!-- for form action -->
|
||||
<!ATTLIST action save (True|False) "False">
|
||||
|
||||
<!ELEMENT containers ((container* | all*)*)>
|
||||
<!ELEMENT services (service*)>
|
||||
|
||||
<!ELEMENT container ((service* | service_access* | service_restriction* | interface* | package* | file* | disknod* | host* | fstab*)*) >
|
||||
<!ATTLIST container name CDATA #REQUIRED >
|
||||
<!ATTLIST container id CDATA #IMPLIED >
|
||||
<!ATTLIST container group CDATA #IMPLIED >
|
||||
|
||||
<!ELEMENT all ((service* | interface* | package* | file* | disknod* | host* | fstab*)*) >
|
||||
|
||||
<!ELEMENT service (#PCDATA)>
|
||||
<!ATTLIST service servicelist CDATA #IMPLIED >
|
||||
<!ELEMENT service ((port* | tcpwrapper* | ip* | interface* | package* | file* | digitalcertificate*)*) >
|
||||
<!ATTLIST service name CDATA #REQUIRED>
|
||||
<!ATTLIST service method (systemd|upstart|apache|network) "systemd">
|
||||
<!ATTLIST service redefine (True|False) "False">
|
||||
|
||||
<!ELEMENT input (#PCDATA)>
|
||||
<!ELEMENT profile (#PCDATA)>
|
||||
@ -85,80 +76,48 @@
|
||||
<!ELEMENT tag (#PCDATA)>
|
||||
<!ELEMENT saltaction (#PCDATA)>
|
||||
|
||||
<!ELEMENT service_access ((port | tcpwrapper)*)>
|
||||
<!ATTLIST service_access service CDATA #REQUIRED >
|
||||
|
||||
<!ELEMENT port (#PCDATA)> <!--port_type-->
|
||||
<!ATTLIST port port_type (PortOption|SymLinkOption) "PortOption">
|
||||
<!ATTLIST port service_accesslist CDATA #IMPLIED >
|
||||
<!ELEMENT port (#PCDATA)>
|
||||
<!ATTLIST port port_type (PortOption|SymLinkOption|variable) "PortOption">
|
||||
<!ATTLIST port portlist CDATA #IMPLIED >
|
||||
<!ATTLIST port protocol (tcp|udp) "tcp">
|
||||
|
||||
<!ELEMENT tcpwrapper (#PCDATA)> <!--tcpwrapper_type-->
|
||||
<!ATTLIST tcpwrapper tcpwrapper_type (UnicodeOption|SymLinkOption) "UnicodeOption">
|
||||
<!ATTLIST tcpwrapper service_accesslist CDATA #IMPLIED >
|
||||
<!ELEMENT tcpwrapper (#PCDATA)>
|
||||
<!ATTLIST tcpwrapper tcpwrapper_type (UnicodeOption|SymLinkOption|variable) "UnicodeOption">
|
||||
<!ATTLIST tcpwrapper tcpwrapperlist CDATA #IMPLIED >
|
||||
|
||||
<!ELEMENT service_restriction (ip*)>
|
||||
<!ATTLIST service_restriction service CDATA #REQUIRED >
|
||||
|
||||
<!ELEMENT ip (#PCDATA)> <!--ip_type-->
|
||||
<!ATTLIST ip service_restrictionlist CDATA #IMPLIED >
|
||||
<!ATTLIST ip ip_type (NetworkOption|SymLinkOption) "NetworkOption">
|
||||
<!ATTLIST ip interface_type (UnicodeOption|SymLinkOption) "UnicodeOption">
|
||||
<!ATTLIST ip interface CDATA #REQUIRED> <!--interface_type-->
|
||||
<!ATTLIST ip netmask_type (NetmaskOption|SymLinkOption) "NetmaskOption">
|
||||
<!ATTLIST ip netmask CDATA "255.255.255.255"> <!--netmask_type-->
|
||||
|
||||
<!ELEMENT interface (#PCDATA)>
|
||||
<!ATTLIST interface interfacelist CDATA #IMPLIED >
|
||||
<!ATTLIST interface linkto CDATA #REQUIRED >
|
||||
<!ATTLIST interface ip CDATA #REQUIRED> <!--SymLinkOption-->
|
||||
<!ATTLIST interface ip_type (SymLinkOption) "SymLinkOption">
|
||||
<!ATTLIST interface mask CDATA #REQUIRED> <!--SymLinkOption-->
|
||||
<!ATTLIST interface mask_type (SymLinkOption) "SymLinkOption">
|
||||
<!ATTLIST interface bcast CDATA #IMPLIED> <!--SymLinkOption-->
|
||||
<!ATTLIST interface bcast_type (SymLinkOption) "SymLinkOption">
|
||||
<!ATTLIST interface gateway CDATA #IMPLIED> <!--SymLinkOption-->
|
||||
<!ATTLIST interface gateway_type (SymLinkOption) "SymLinkOption">
|
||||
<!ATTLIST interface method (bridge|macvlan) "macvlan" >
|
||||
<!ATTLIST interface redefine (True|False) "False">
|
||||
|
||||
<!ELEMENT host EMPTY >
|
||||
<!ATTLIST host hostlist CDATA #IMPLIED >
|
||||
<!ATTLIST host name CDATA #REQUIRED > <!--SymLinkOption-->
|
||||
<!ATTLIST host name_type (SymLinkOption) "SymLinkOption">
|
||||
<!ATTLIST host ip CDATA #REQUIRED > <!--SymLinkOption-->
|
||||
<!ATTLIST host ip_type (SymLinkOption) "SymLinkOption">
|
||||
<!ATTLIST host crossed (True|False) "True" >
|
||||
<!ATTLIST host comment CDATA #IMPLIED >
|
||||
|
||||
<!ELEMENT fstab EMPTY >
|
||||
<!ATTLIST fstab name CDATA #REQUIRED> <!--name_type-->
|
||||
<!ATTLIST fstab name_type (FilenameOption|SymLinkOption) "FilenameOption">
|
||||
<!ATTLIST fstab type (bind|normal) "bind">
|
||||
<!ATTLIST fstab fstype (auto|ext3|ext4|nfs|smb) "auto">
|
||||
<!ATTLIST fstab mount_point CDATA #IMPLIED> <!--mount_point_type-->
|
||||
<!ATTLIST fstab mount_point_type (FilenameOption|SymLinkOption) "FilenameOption">
|
||||
<!ATTLIST fstab options CDATA #IMPLIED>
|
||||
<!ATTLIST fstab checks CDATA #IMPLIED>
|
||||
<!ATTLIST fstab fstablist CDATA #IMPLIED>
|
||||
<!ELEMENT ip (#PCDATA)>
|
||||
<!ATTLIST ip iplist CDATA #IMPLIED >
|
||||
<!ATTLIST ip ip_type (NetworkOption|SymLinkOption|variable) "NetworkOption">
|
||||
<!ATTLIST ip interface_type (UnicodeOption|SymLinkOption|variable) "UnicodeOption">
|
||||
<!ATTLIST ip interface CDATA #REQUIRED>
|
||||
<!ATTLIST ip netmask_type (NetmaskOption|SymLinkOption|variable) "NetmaskOption">
|
||||
<!ATTLIST ip netmask CDATA "255.255.255.255">
|
||||
|
||||
<!ELEMENT package (#PCDATA)>
|
||||
<!ATTLIST package packagelist CDATA #IMPLIED>
|
||||
|
||||
<!ELEMENT disknod (#PCDATA)>
|
||||
<!ATTLIST package packagelist CDATA #IMPLIED >
|
||||
|
||||
<!ELEMENT file EMPTY>
|
||||
<!ATTLIST file name CDATA #REQUIRED >
|
||||
<!ATTLIST file file_type (UnicodeOption|SymLinkOption|variable) "UnicodeOption">
|
||||
<!ATTLIST file variable CDATA #IMPLIED>
|
||||
<!ATTLIST file variable_type (variable) "variable">
|
||||
<!ATTLIST file source CDATA #IMPLIED>
|
||||
<!ATTLIST file mode CDATA #IMPLIED >
|
||||
<!ATTLIST file owner CDATA #IMPLIED >
|
||||
<!ATTLIST file group CDATA #IMPLIED >
|
||||
<!ATTLIST file mode CDATA "0644">
|
||||
<!ATTLIST file owner CDATA "root">
|
||||
<!ATTLIST file group CDATA "root">
|
||||
<!ATTLIST file filelist CDATA #IMPLIED >
|
||||
<!ATTLIST file mkdir (True|False) "False">
|
||||
<!ATTLIST file rm (True|False) "False">
|
||||
<!ATTLIST file del_comment CDATA #IMPLIED >
|
||||
<!ATTLIST file redefine (True|False) "False">
|
||||
|
||||
<!ELEMENT digitalcertificate EMPTY>
|
||||
<!ATTLIST digitalcertificate name CDATA #REQUIRED >
|
||||
<!ATTLIST digitalcertificate digitalcertificate_type (variable) "variable">
|
||||
<!ATTLIST digitalcertificate certificate CDATA #REQUIRED >
|
||||
<!ATTLIST digitalcertificate certificate_type (variable) "variable">
|
||||
<!ATTLIST digitalcertificate type CDATA #REQUIRED >
|
||||
<!ATTLIST digitalcertificate ca CDATA #REQUIRED >
|
||||
|
||||
<!ELEMENT variables (family*, separators*)>
|
||||
<!ELEMENT family (#PCDATA | variable)*>
|
||||
<!ATTLIST family name CDATA #REQUIRED>
|
||||
@ -166,6 +125,7 @@
|
||||
<!ATTLIST family mode (basic|normal|expert) "basic">
|
||||
<!ATTLIST family icon CDATA #IMPLIED>
|
||||
<!ATTLIST family hidden (True|False) "False">
|
||||
<!ATTLIST family dynamic CDATA #IMPLIED>
|
||||
|
||||
<!ELEMENT variable (#PCDATA | value)*>
|
||||
<!ATTLIST variable name CDATA #REQUIRED>
|
||||
@ -174,6 +134,7 @@
|
||||
<!ATTLIST variable hidden (True|False) "False">
|
||||
<!ATTLIST variable disabled (True|False) "False">
|
||||
<!ATTLIST variable multi (True|False) "False">
|
||||
<!ATTLIST variable submulti (True|False) "False">
|
||||
<!ATTLIST variable redefine (True|False) "False">
|
||||
<!ATTLIST variable exists (True|False) "True">
|
||||
<!ATTLIST variable mandatory (True|False) "False">
|
||||
@ -182,6 +143,7 @@
|
||||
<!ATTLIST variable mode (basic|normal|expert) "normal">
|
||||
<!ATTLIST variable remove_check (True|False) "False">
|
||||
<!ATTLIST variable remove_condition (True|False) "False">
|
||||
<!ATTLIST variable test CDATA #IMPLIED>
|
||||
|
||||
<!ELEMENT separators (separator*)>
|
||||
|
||||
@ -212,18 +174,18 @@
|
||||
|
||||
<!ELEMENT group (slave+)>
|
||||
<!ATTLIST group master CDATA #REQUIRED>
|
||||
<!ATTLIST group description CDATA #IMPLIED>
|
||||
|
||||
<!ELEMENT param (#PCDATA)>
|
||||
<!ATTLIST param type (string|eole|number|container|context|python) "string">
|
||||
<!ATTLIST param type (string|variable|number|python) "string">
|
||||
<!ATTLIST param name CDATA #IMPLIED>
|
||||
<!ATTLIST param hidden (True|False) "True">
|
||||
<!ATTLIST param optional (True|False) "False">
|
||||
|
||||
<!ELEMENT target (#PCDATA)>
|
||||
<!ATTLIST target type (family|filelist|servicelist|interfacelist|variable|service_accesslist|service_restrictionlist|hostlist|fstablist|actionlist) "variable">
|
||||
<!ATTLIST target type (family|variable|filelist|iplist|portlist|tcpwrapperlist|packagelist|actionlist) "variable">
|
||||
<!ATTLIST target optional (True|False) "False">
|
||||
|
||||
<!ELEMENT slave (#PCDATA)>
|
||||
|
||||
<!ELEMENT help ((variable* | family*)*)>
|
||||
|
@ -6,16 +6,14 @@ from os import listdir
|
||||
#from ast import literal_eval
|
||||
from lxml.etree import parse, DTD
|
||||
|
||||
from tiramisu.option import (StrOption, OptionDescription, PortOption,
|
||||
IntOption, ChoiceOption, BoolOption, SymLinkOption, IPOption,
|
||||
NetworkOption, NetmaskOption, DomainnameOption, BroadcastOption,
|
||||
URLOption, EmailOption, FilenameOption, UsernameOption, DateOption,
|
||||
PasswordOption, BoolOption, MACOption, Leadership)
|
||||
from tiramisu import Config, MetaConfig, MixConfig
|
||||
from tiramisu.setting import groups
|
||||
from tiramisu import (StrOption, OptionDescription, DynOptionDescription, PortOption,
|
||||
IntOption, ChoiceOption, BoolOption, SymLinkOption, IPOption,
|
||||
NetworkOption, NetmaskOption, DomainnameOption, BroadcastOption,
|
||||
URLOption, EmailOption, FilenameOption, UsernameOption, DateOption,
|
||||
PasswordOption, BoolOption, MACOption, Leadership, submulti,
|
||||
Params, ParamSelfOption, ParamOption, ParamValue, Calculation, calc_value,
|
||||
groups, owners)
|
||||
from tiramisu.error import ConfigError
|
||||
from tiramisu.setting import owners
|
||||
from tiramisu import Params, ParamOption, ParamValue, ParamContext, Calculation, calc_value
|
||||
|
||||
from .config import dtdfilename
|
||||
from .i18n import _
|
||||
@ -23,9 +21,21 @@ from .i18n import _
|
||||
from .xmlreflector import HIGH_COMPATIBILITY
|
||||
#from . import eosfunc
|
||||
from .objspace import CreoleObjSpace
|
||||
from .utils import normalize_family
|
||||
import imp
|
||||
|
||||
|
||||
FUNC_TO_DICT = ['valid_not_equal']
|
||||
|
||||
|
||||
class ConvertDynOptionDescription(DynOptionDescription):
|
||||
def convert_suffix_to_path(self, suffix):
|
||||
if not isinstance(suffix, str):
|
||||
suffix = str(suffix)
|
||||
return normalize_family(suffix,
|
||||
check_name=False)
|
||||
|
||||
|
||||
class CreoleLoaderError(Exception):
|
||||
pass
|
||||
|
||||
@ -81,7 +91,9 @@ CONVERT_OPTION = {'number': dict(opttype=IntOption),
|
||||
'hostname_strict': dict(opttype=DomainnameOption, initkwargs={'type': 'hostname', 'allow_ip': False}),
|
||||
'web_address': dict(opttype=URLOption, initkwargs={'allow_ip': True, 'allow_without_dot': True}),
|
||||
'port': dict(opttype=PortOption, initkwargs={'allow_private': True}),
|
||||
'mac': dict(opttype=MACOption)
|
||||
'mac': dict(opttype=MACOption),
|
||||
'cidr': dict(opttype=IPOption, initkwargs={'cidr': True}),
|
||||
'network_cidr': dict(opttype=NetworkOption, initkwargs={'cidr': True}),
|
||||
}
|
||||
|
||||
|
||||
@ -117,9 +129,12 @@ class PopulateTiramisuObjects(object):
|
||||
|
||||
def make_tiramisu_objects(self, xmlroot, creolefunc_file):
|
||||
elt = Elt({'name': 'baseoption'})
|
||||
family = Family(elt, self.booleans, self.storage)
|
||||
if creolefunc_file is None:
|
||||
self.eosfunc = None
|
||||
else:
|
||||
self.eosfunc = imp.load_source('eosfunc', creolefunc_file)
|
||||
family = Family(elt, self.booleans, self.storage, self.eosfunc)
|
||||
self.storage.add('.', family)
|
||||
self.eosfunc = imp.load_source('eosfunc', creolefunc_file)
|
||||
|
||||
elts = {}
|
||||
for elt in xmlroot:
|
||||
@ -167,7 +182,7 @@ class PopulateTiramisuObjects(object):
|
||||
force_icon = False
|
||||
else:
|
||||
force_icon = not subpath.startswith('containers') and not subpath.startswith('actions')
|
||||
family = Family(elt, self.booleans, self.storage, force_icon)
|
||||
family = Family(elt, self.booleans, self.storage, self.eosfunc, force_icon)
|
||||
path = self._build_path(subpath, elt)
|
||||
self.storage.add(path, family)
|
||||
return family
|
||||
@ -181,7 +196,7 @@ class PopulateTiramisuObjects(object):
|
||||
|
||||
def _iter_leader(self, leader, subpath):
|
||||
subpath = self._build_path(subpath, leader)
|
||||
family = Family(leader, self.booleans, self.storage)
|
||||
family = Family(leader, self.booleans, self.storage, self.eosfunc)
|
||||
family.set_leader()
|
||||
self.storage.add(subpath, family)
|
||||
leader_name = None
|
||||
@ -256,36 +271,6 @@ class PopulateTiramisuObjects(object):
|
||||
self.separators[separator.attrib['name']] = info
|
||||
elt.add_information('separator', info)
|
||||
|
||||
def build(self, persistent=False, session_id=None, meta_config=False):
|
||||
if meta_config:
|
||||
optiondescription = self.storage.paths['.'].get()
|
||||
config = MetaConfig([],
|
||||
optiondescription=optiondescription,
|
||||
persistent=persistent,
|
||||
session_id=session_id)
|
||||
mixconfig = MixConfig(children=[],
|
||||
optiondescription=optiondescription,
|
||||
persistent=persistent,
|
||||
session_id='m_' + session_id)
|
||||
config.config.add(mixconfig)
|
||||
else:
|
||||
config = Config(self.storage.paths['.'].get(),
|
||||
persistent=persistent,
|
||||
session_id=session_id)
|
||||
config.information.set('force_store_vars', self.force_store_values)
|
||||
config.information.set('force_store_values', list(self.force_store_values))
|
||||
# XXX really usefull?
|
||||
ro_append = frozenset(config.property.getdefault('read_only', 'append') - {'force_store_value'})
|
||||
rw_append = frozenset(config.property.getdefault('read_write', 'append') - {'force_store_value'})
|
||||
config.property.setdefault(ro_append, 'read_only', 'append')
|
||||
config.property.setdefault(rw_append, 'read_write', 'append')
|
||||
|
||||
config.property.read_only()
|
||||
config.permissive.add('basic')
|
||||
config.permissive.add('normal')
|
||||
config.permissive.add('expert')
|
||||
return config
|
||||
|
||||
|
||||
class ElementStorage:
|
||||
def __init__(self):
|
||||
@ -331,15 +316,19 @@ class Variable(Common):
|
||||
self.attrib['validators'] = []
|
||||
self.eosfunc = eosfunc
|
||||
self.storage = storage
|
||||
is_submulti = False
|
||||
for key, value in elt.attrib.items():
|
||||
if key in booleans:
|
||||
if value == 'True':
|
||||
value = True
|
||||
elif value == 'False':
|
||||
value = False
|
||||
elif key == 'multi' and value == 'submulti':
|
||||
is_submulti = True
|
||||
value = submulti
|
||||
else:
|
||||
raise CreoleLoaderError(_('unknown value {} for {}').format(value, key))
|
||||
if key == 'help':
|
||||
if key in ['help', 'test']:
|
||||
self.add_information(key, value)
|
||||
elif key == 'type':
|
||||
pass
|
||||
@ -373,7 +362,7 @@ class Variable(Common):
|
||||
self.attrib['properties'].append(child.text)
|
||||
elif child.tag == 'value':
|
||||
if child.attrib.get('type') == 'calculation':
|
||||
if child.text.strip():
|
||||
if child.text is not None and child.text.strip():
|
||||
self.attrib['default'] = (child.text.strip(),)
|
||||
else:
|
||||
params = []
|
||||
@ -385,13 +374,22 @@ class Variable(Common):
|
||||
type_ = CONVERT_OPTION[child.attrib['type']]['opttype']
|
||||
else:
|
||||
type_ = self.object_type
|
||||
if self.attrib['multi'] and not is_follower:
|
||||
if self.attrib['multi'] is True and not is_follower:
|
||||
if 'default' not in self.attrib:
|
||||
self.attrib['default'] = []
|
||||
value = convert_tiramisu_value(child.text, type_)
|
||||
self.attrib['default'].append(value)
|
||||
if 'default_multi' not in self.attrib and not is_leader:
|
||||
self.attrib['default_multi'] = value
|
||||
elif self.attrib['multi'] == submulti:
|
||||
if 'default' not in self.attrib:
|
||||
self.attrib['default'] = []
|
||||
value = convert_tiramisu_value(child.text, type_)
|
||||
if not isinstance(value, list) and not is_follower:
|
||||
value = [value]
|
||||
self.attrib['default'].append(value)
|
||||
if 'default_multi' not in self.attrib and not is_leader:
|
||||
self.attrib['default_multi'] = value
|
||||
else:
|
||||
if 'default' in self.attrib:
|
||||
raise CreoleLoaderError(_('default value already set for {}'
|
||||
@ -425,7 +423,7 @@ class Variable(Common):
|
||||
name = param.attrib.get('name', '')
|
||||
if param.attrib['type'] == 'string':
|
||||
value = param.text
|
||||
elif param.attrib['type'] == 'eole':
|
||||
elif param.attrib['type'] == 'variable':
|
||||
transitive = param.attrib.get('transitive', 'False')
|
||||
if transitive == 'True':
|
||||
transitive = True
|
||||
@ -456,12 +454,18 @@ class Variable(Common):
|
||||
ret = []
|
||||
for value in values:
|
||||
if isinstance(value, tuple):
|
||||
args = []
|
||||
if key == 'validators':
|
||||
args = [ParamSelfOption()]
|
||||
else:
|
||||
args = []
|
||||
kwargs = {}
|
||||
if len(value) == 3:
|
||||
for param in value[1]:
|
||||
if isinstance(param[1], list):
|
||||
param_value = ParamOption(self.storage.get(param[1][0]).get(), notraisepropertyerror=param[1][1])
|
||||
if value[0] in FUNC_TO_DICT:
|
||||
param_value = ParamOption(self.storage.get(param[1][0]).get(), notraisepropertyerror=param[1][1], todict=True)
|
||||
else:
|
||||
param_value = ParamOption(self.storage.get(param[1][0]).get(), notraisepropertyerror=param[1][1])
|
||||
else:
|
||||
param_value = ParamValue(param[1])
|
||||
if not param[0]:
|
||||
@ -491,7 +495,6 @@ class Variable(Common):
|
||||
if not self.attrib['validators']:
|
||||
del self.attrib['validators']
|
||||
try:
|
||||
print(self.attrib)
|
||||
option = self.object_type(**self.attrib)
|
||||
except Exception as err:
|
||||
import traceback
|
||||
@ -505,7 +508,7 @@ class Variable(Common):
|
||||
|
||||
|
||||
class Family(Common):
|
||||
def __init__(self, elt, booleans, storage, force_icon=False):
|
||||
def __init__(self, elt, booleans, storage, eosfunc, force_icon=False):
|
||||
self.option = None
|
||||
self.attrib = {}
|
||||
self.is_leader = False
|
||||
@ -515,6 +518,7 @@ class Family(Common):
|
||||
self.informations = {}
|
||||
self.children = []
|
||||
self.storage = storage
|
||||
self.eosfunc = eosfunc
|
||||
self.attrib['properties'] = []
|
||||
for key, value in elt.attrib.items():
|
||||
if key in booleans:
|
||||
@ -559,11 +563,16 @@ class Family(Common):
|
||||
self.attrib['children'].append(child.get())
|
||||
self.build_properties()
|
||||
try:
|
||||
if not self.is_leader:
|
||||
if 'dynamic' in self.attrib:
|
||||
dynamic = self.storage.get(self.attrib['dynamic']).get()
|
||||
del self.attrib['dynamic']
|
||||
self.attrib['suffixes'] = Calculation(self.eosfunc.calc_value,
|
||||
Params((ParamOption(dynamic),)))
|
||||
option = ConvertDynOptionDescription(**self.attrib)
|
||||
elif not self.is_leader:
|
||||
option = OptionDescription(**self.attrib)
|
||||
else:
|
||||
option = Leadership(**self.attrib)
|
||||
#option = OptionDescription(**self.attrib)
|
||||
except Exception as err:
|
||||
raise CreoleLoaderError(_('cannot create optiondescription {}: {}').format(self.attrib['name'], err))
|
||||
for key, value in self.informations.items():
|
||||
@ -573,3 +582,13 @@ class Family(Common):
|
||||
# self.option.impl_set_group_type(groups.leader)
|
||||
|
||||
return self.option
|
||||
|
||||
|
||||
def load(xmlroot: str,
|
||||
dtd_path: str,
|
||||
funcs_path: str):
|
||||
tiramisu_objects = PopulateTiramisuObjects()
|
||||
tiramisu_objects.parse_dtd(dtd_path)
|
||||
tiramisu_objects.make_tiramisu_objects(xmlroot,
|
||||
funcs_path)
|
||||
return tiramisu_objects.storage.paths['.'].get()
|
@ -30,16 +30,16 @@ from json import dump
|
||||
|
||||
from .i18n import _
|
||||
from .xmlreflector import XMLReflector, HIGH_COMPATIBILITY
|
||||
from .annotator import ERASED_ATTRIBUTES, ActionAnnotator, ContainerAnnotator, SpaceAnnotator
|
||||
from .annotator import ERASED_ATTRIBUTES, ActionAnnotator, ServiceAnnotator, SpaceAnnotator
|
||||
from .utils import normalize_family
|
||||
from .error import CreoleOperationError, SpaceObjShallNotBeUpdated, CreoleDictConsistencyError
|
||||
|
||||
# CreoleObjSpace's elements like 'family' or 'slave', that shall be forced to the Redefinable type
|
||||
FORCE_REDEFINABLES = ('family', 'slave', 'container', 'disknod', 'variables', 'family_action')
|
||||
FORCE_REDEFINABLES = ('family', 'slave', 'service', 'disknod', 'variables', 'family_action')
|
||||
# CreoleObjSpace's elements that shall be forced to the UnRedefinable type
|
||||
FORCE_UNREDEFINABLES = ('value', 'input', 'profile', 'ewtapp', 'tag', 'saltaction')
|
||||
# CreoleObjSpace's elements that shall be set to the UnRedefinable type
|
||||
UNREDEFINABLE = ('multi', 'type')
|
||||
UNREDEFINABLE = ('submulti', 'multi', 'type')
|
||||
|
||||
PROPERTIES = ('hidden', 'frozen', 'auto_freeze', 'auto_save', 'force_default_on_freeze',
|
||||
'force_store_value', 'disabled', 'mandatory')
|
||||
@ -47,6 +47,8 @@ CONVERT_PROPERTIES = {'auto_save': ['force_store_value'], 'auto_freeze': ['force
|
||||
|
||||
RENAME_ATTIBUTES = {'description': 'doc'}
|
||||
|
||||
INCOMPATIBLE_ATTRIBUTES = [['multi', 'submulti']]
|
||||
|
||||
#TYPE_TARGET_CONDITION = ('variable', 'family')
|
||||
|
||||
# _____________________________________________________________________________
|
||||
@ -86,12 +88,8 @@ class CreoleObjSpace(object):
|
||||
self.redefine_variables = None
|
||||
self.probe_variables = []
|
||||
|
||||
# elt container's attrs list
|
||||
self.container_elt_attr_list = [] #
|
||||
# ['variable', 'separator', 'family']
|
||||
self.forced_text_elts = set()
|
||||
# ['disknod', 'follower', 'target', 'service', 'package', 'ip', 'value', 'tcpwrapper',
|
||||
# 'interface', 'input', 'port']
|
||||
self.forced_text_elts_as_name = set(['choice', 'property'])
|
||||
self.forced_choice_option = {}
|
||||
self.paths = Path()
|
||||
@ -106,8 +104,7 @@ class CreoleObjSpace(object):
|
||||
forced_text_elt = False
|
||||
if elt.type == 'mixed':
|
||||
forced_text_elt = True
|
||||
if elt.name == 'container':
|
||||
self.container_elt_attr_list = [elt.content.left.name]
|
||||
if elt.name == 'service':
|
||||
self.parse_dtd_right_left_elt(elt.content)
|
||||
for attr in elt.iterattributes():
|
||||
atomic = False
|
||||
@ -152,10 +149,7 @@ class CreoleObjSpace(object):
|
||||
|
||||
def parse_dtd_right_left_elt(self, elt):
|
||||
if elt.right.type == 'or':
|
||||
self.container_elt_attr_list.append(elt.right.left.name)
|
||||
self.parse_dtd_right_left_elt(elt.right)
|
||||
else:
|
||||
self.container_elt_attr_list.append(elt.right.name)
|
||||
|
||||
def _convert_boolean(self, value): # pylint: disable=R0201
|
||||
"""Boolean coercion. The Creole XML may contain srings like `True` or `False`
|
||||
@ -297,7 +291,7 @@ class CreoleObjSpace(object):
|
||||
def create_tree_structure(self, space, child, creoleobj): # pylint: disable=R0201
|
||||
"""
|
||||
Builds the tree structure of the object space here
|
||||
we set containers attributes in order to be populated later on
|
||||
we set services attributes in order to be populated later on
|
||||
for example::
|
||||
|
||||
space = Family()
|
||||
@ -363,6 +357,15 @@ class CreoleObjSpace(object):
|
||||
'not {}').format(attr, val))
|
||||
if not (attr == 'name' and getattr(creoleobj, 'name', None) != None):
|
||||
setattr(creoleobj, attr, val)
|
||||
keys = list(vars(creoleobj).keys())
|
||||
for incompatible in INCOMPATIBLE_ATTRIBUTES:
|
||||
found = False
|
||||
for inc in incompatible:
|
||||
if inc in keys:
|
||||
if found:
|
||||
raise CreoleDictConsistencyError(_('those attributes are incompatible {}').format(incompatible))
|
||||
found = True
|
||||
|
||||
|
||||
def _creoleobj_tree_visitor(self, child, creoleobj, namespace):
|
||||
"""Creole object tree manipulations
|
||||
@ -458,7 +461,7 @@ class CreoleObjSpace(object):
|
||||
|
||||
def space_visitor(self, eosfunc_file): # pylint: disable=C0111
|
||||
ActionAnnotator(self)
|
||||
ContainerAnnotator(self)
|
||||
ServiceAnnotator(self)
|
||||
SpaceAnnotator(self, eosfunc_file)
|
||||
|
||||
def save(self, filename, force_no_save=False):
|
||||
@ -513,11 +516,9 @@ class CreoleObjSpace(object):
|
||||
for subspace in space:
|
||||
if isinstance(subspace, self.Leadership):
|
||||
_name = 'leader'
|
||||
subspace.doc = subspace.variable[0].description
|
||||
#subspace.doc = 'Leadership {}'.format(subspace.name)
|
||||
else:
|
||||
_name = name
|
||||
if name in ['containers', 'variables', 'actions']:
|
||||
if name in ['services', 'variables', 'actions']:
|
||||
_name = 'family'
|
||||
if HIGH_COMPATIBILITY and not hasattr(subspace, 'doc'):
|
||||
subspace.doc = ''
|
||||
@ -526,7 +527,7 @@ class CreoleObjSpace(object):
|
||||
child_node = SubElement(node, _name)
|
||||
self._xml_export(child_node, subspace, _name)
|
||||
elif isinstance(space, self.Atom):
|
||||
if name == 'containers':
|
||||
if name == 'services':
|
||||
child_node = SubElement(node, 'family')
|
||||
child_node.attrib['name'] = name
|
||||
else:
|
||||
@ -603,7 +604,9 @@ class Path(object):
|
||||
def get_family_path(self, name, current_namespace): # pylint: disable=C0111
|
||||
if current_namespace is None: # pragma: no cover
|
||||
raise CreoleOperationError('current_namespace must not be None')
|
||||
dico = self.families[normalize_family(name, check_name=False)]
|
||||
dico = self.families[normalize_family(name,
|
||||
check_name=False,
|
||||
allow_dot=True)]
|
||||
if dico['namespace'] != 'creole' and current_namespace != dico['namespace']:
|
||||
raise CreoleDictConsistencyError(_('A family located in the {} namespace '
|
||||
'shall not be used in the {} namespace').format(
|
||||
@ -652,7 +655,7 @@ class Path(object):
|
||||
raise CreoleOperationError('current_namespace must not be None')
|
||||
dico = self._get_variable(name)
|
||||
if not allow_source:
|
||||
if dico['namespace'] != 'creole' and current_namespace != dico['namespace']:
|
||||
if dico['namespace'] not in ['creole', 'services'] and current_namespace != dico['namespace']:
|
||||
raise CreoleDictConsistencyError(_('A variable located in the {} namespace '
|
||||
'shall not be used in the {} namespace').format(
|
||||
dico['namespace'], current_namespace))
|
443
src/rougail/template.py
Normal file
443
src/rougail/template.py
Normal file
@ -0,0 +1,443 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Gestion du mini-langage de template
|
||||
On travaille sur les fichiers cibles
|
||||
"""
|
||||
|
||||
import imp
|
||||
import sys
|
||||
from shutil import copy
|
||||
import logging
|
||||
from typing import Dict, Any
|
||||
|
||||
from subprocess import call
|
||||
from os import listdir, unlink, makedirs
|
||||
from os.path import dirname, basename, join, split, isfile, isdir
|
||||
|
||||
from tempfile import mktemp
|
||||
|
||||
from Cheetah import Parser
|
||||
|
||||
|
||||
# l'encoding du template est déterminé par une regexp (encodingDirectiveRE dans Parser.py)
|
||||
# il cherche un ligne qui ressemble à '#encoding: utf-8
|
||||
# cette classe simule le module 're' et retourne toujours l'encoding utf-8
|
||||
# 6224
|
||||
class FakeEncoding:
|
||||
def groups(self):
|
||||
return ('utf-8',)
|
||||
|
||||
def search(self, *args):
|
||||
return self
|
||||
Parser.encodingDirectiveRE = FakeEncoding()
|
||||
|
||||
|
||||
from Cheetah.Template import Template as ChtTemplate
|
||||
from Cheetah.NameMapper import NotFound as CheetahNotFound
|
||||
|
||||
from tiramisu import Config
|
||||
from tiramisu.error import PropertiesOptionError
|
||||
|
||||
from .config import patch_dir
|
||||
from .error import FileNotFound, TemplateError, TemplateDisabled
|
||||
from .i18n import _
|
||||
from .utils import normalize_family
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
log.addHandler(logging.NullHandler())
|
||||
|
||||
class IsDefined:
|
||||
"""
|
||||
filtre permettant de ne pas lever d'exception au cas où
|
||||
la variable Creole n'est pas définie
|
||||
"""
|
||||
def __init__(self, context):
|
||||
self.context = context
|
||||
|
||||
def __call__(self, varname):
|
||||
if '.' in varname:
|
||||
splitted_var = varname.split('.')
|
||||
if len(splitted_var) != 2:
|
||||
msg = _("Group variables must be of type master.slave")
|
||||
raise KeyError(msg)
|
||||
master, slave = splitted_var
|
||||
if master in self.context:
|
||||
return slave in self.context[master].slave.keys()
|
||||
return False
|
||||
else:
|
||||
return varname in self.context
|
||||
|
||||
|
||||
class CreoleGet:
|
||||
def __init__(self, context):
|
||||
self.context = context
|
||||
|
||||
def __call__(self, varname):
|
||||
return self.context[varname]
|
||||
|
||||
def __getitem__(self, varname):
|
||||
"""For bracket and dotted notation
|
||||
"""
|
||||
return self.context[varname]
|
||||
|
||||
def __contains__(self, varname):
|
||||
"""Check variable existence in context
|
||||
"""
|
||||
return varname in self.context
|
||||
|
||||
|
||||
@classmethod
|
||||
def cl_compile(kls, *args, **kwargs):
|
||||
kwargs['compilerSettings'] = {'directiveStartToken' : '%',
|
||||
'cheetahVarStartToken' : '%%',
|
||||
'EOLSlurpToken' : '%',
|
||||
'PSPStartToken' : 'µ' * 10,
|
||||
'PSPEndToken' : 'µ' * 10,
|
||||
'commentStartToken' : 'µ' * 10,
|
||||
'commentEndToken' : 'µ' * 10,
|
||||
'multiLineCommentStartToken' : 'µ' * 10,
|
||||
'multiLineCommentEndToken' : 'µ' * 10}
|
||||
return kls.old_compile(*args, **kwargs)
|
||||
ChtTemplate.old_compile = ChtTemplate.compile
|
||||
ChtTemplate.compile = cl_compile
|
||||
|
||||
|
||||
class CreoleClient:
|
||||
def __init__(self,
|
||||
config: Config):
|
||||
self.config = config
|
||||
|
||||
|
||||
class CheetahTemplate(ChtTemplate):
|
||||
"""classe pour personnaliser et faciliter la construction
|
||||
du template Cheetah
|
||||
"""
|
||||
def __init__(self,
|
||||
filename: str,
|
||||
context,
|
||||
eosfunc: Dict,
|
||||
destfilename,
|
||||
variable):
|
||||
"""Initialize Creole CheetahTemplate
|
||||
"""
|
||||
extra_context = {'is_defined' : IsDefined(context),
|
||||
'normalize_family': normalize_family,
|
||||
'rougail_filename': destfilename
|
||||
}
|
||||
if variable:
|
||||
extra_context['rougail_variable'] = variable
|
||||
ChtTemplate.__init__(self,
|
||||
file=filename,
|
||||
searchList=[context, eosfunc, extra_context])
|
||||
|
||||
|
||||
class CreoleLeader:
|
||||
def __init__(self, value, slave=None, index=None):
|
||||
"""
|
||||
On rend la variable itérable pour pouvoir faire:
|
||||
for ip in iplist:
|
||||
print(ip.network)
|
||||
print(ip.netmask)
|
||||
print(ip)
|
||||
index is used for CreoleLint
|
||||
"""
|
||||
self._value = value
|
||||
if slave is not None:
|
||||
self.slave = slave
|
||||
else:
|
||||
self.slave = {}
|
||||
self._index = index
|
||||
|
||||
def __getattr__(self, name):
|
||||
"""Get slave variable or attribute of master value.
|
||||
|
||||
If the attribute is a name of a slave variable, return its value.
|
||||
Otherwise, returns the requested attribute of master value.
|
||||
"""
|
||||
if name in self.slave:
|
||||
value = self.slave[name]
|
||||
if isinstance(value, PropertiesOptionError):
|
||||
raise AttributeError()
|
||||
return value
|
||||
else:
|
||||
return getattr(self._value, name)
|
||||
|
||||
def __getitem__(self, index):
|
||||
"""Get a master.slave at requested index.
|
||||
"""
|
||||
ret = {}
|
||||
for key, values in self.slave.items():
|
||||
ret[key] = values[index]
|
||||
return CreoleLeader(self._value[index], ret, index)
|
||||
|
||||
def __iter__(self):
|
||||
"""Iterate over master.slave.
|
||||
|
||||
Return synchronised value of master.slave.
|
||||
"""
|
||||
for i in range(len(self._value)):
|
||||
ret = {}
|
||||
for key, values in self.slave.items():
|
||||
ret[key] = values[i]
|
||||
yield CreoleLeader(self._value[i], ret, i)
|
||||
|
||||
def __len__(self):
|
||||
"""Delegate to master value
|
||||
"""
|
||||
return len(self._value)
|
||||
|
||||
def __repr__(self):
|
||||
"""Show CreoleLeader as dictionary.
|
||||
|
||||
The master value is stored under 'value' key.
|
||||
The slaves are stored under 'slave' key.
|
||||
"""
|
||||
return repr({'value': self._value, 'slave': self.slave})
|
||||
|
||||
def __eq__(self, value):
|
||||
return value == self._value
|
||||
|
||||
def __ne__(self, value):
|
||||
return value != self._value
|
||||
|
||||
def __lt__(self, value):
|
||||
return self._value < value
|
||||
|
||||
def __le__(self, value):
|
||||
return self._value <= value
|
||||
|
||||
def __gt__(self, value):
|
||||
return self._value > value
|
||||
|
||||
def __ge__(self, value):
|
||||
return self._value >= value
|
||||
|
||||
def __str__(self):
|
||||
"""Delegate to master value
|
||||
"""
|
||||
return str(self._value)
|
||||
|
||||
def __add__(self, val):
|
||||
return self._value.__add__(val)
|
||||
|
||||
def __radd__(self, val):
|
||||
return val + self._value
|
||||
|
||||
def __contains__(self, item):
|
||||
return item in self._value
|
||||
|
||||
async def add_slave(self, config, name, path):
|
||||
if isinstance(self._value, list):
|
||||
values = []
|
||||
for idx in range(len(self._value)):
|
||||
try:
|
||||
values.append(await config.option(path, idx).value.get())
|
||||
except PropertiesOptionError as err:
|
||||
values.append(err)
|
||||
else:
|
||||
raise Exception('hu?')
|
||||
self.slave[name] = values
|
||||
|
||||
|
||||
class CreoleExtra:
|
||||
def __init__(self,
|
||||
suboption: Dict) -> None:
|
||||
self.suboption = suboption
|
||||
|
||||
def __getattr__(self,
|
||||
key: str) -> Any:
|
||||
return self.suboption[key]
|
||||
|
||||
def __repr__(self):
|
||||
return self.suboption.__str__()
|
||||
|
||||
|
||||
class CreoleTemplateEngine:
|
||||
"""Engine to process Creole cheetah template
|
||||
"""
|
||||
def __init__(self,
|
||||
config: Config,
|
||||
eosfunc_file: str,
|
||||
distrib_dir: str,
|
||||
tmp_dir: str,
|
||||
dest_dir:str) -> None:
|
||||
self.config = config
|
||||
self.dest_dir = dest_dir
|
||||
self.tmp_dir = tmp_dir
|
||||
self.distrib_dir = distrib_dir
|
||||
eos = {}
|
||||
if eosfunc_file is not None:
|
||||
eosfunc = imp.load_source('eosfunc', eosfunc_file)
|
||||
for func in dir(eosfunc):
|
||||
if not func.startswith('_'):
|
||||
eos[func] = getattr(eosfunc, func)
|
||||
self.eosfunc = eos
|
||||
self.creole_variables_dict = {}
|
||||
|
||||
async def load_eole_variables_creole(self,
|
||||
optiondescription):
|
||||
for option in await optiondescription.list('all'):
|
||||
if await option.option.isoptiondescription():
|
||||
if await option.option.isleadership():
|
||||
for idx, suboption in enumerate(await option.list('all')):
|
||||
if idx == 0:
|
||||
leader = CreoleLeader(await suboption.value.get())
|
||||
self.creole_variables_dict[await suboption.option.name()] = leader
|
||||
else:
|
||||
await leader.add_slave(self.config,
|
||||
await suboption.option.name(),
|
||||
await suboption.option.path())
|
||||
else:
|
||||
await self.load_eole_variables_creole(option)
|
||||
else:
|
||||
self.creole_variables_dict[await option.option.name()] = await option.value.get()
|
||||
|
||||
async def load_eole_variables(self,
|
||||
namespace,
|
||||
optiondescription):
|
||||
families = {}
|
||||
for family in await optiondescription.list('all'):
|
||||
variables = {}
|
||||
for variable in await family.list('all'):
|
||||
if await variable.option.isoptiondescription() and await variable.option.isleadership():
|
||||
for idx, suboption in enumerate(await variable.list('all')):
|
||||
if idx == 0:
|
||||
leader = CreoleLeader(await suboption.value.get())
|
||||
leader_name = await suboption.option.name()
|
||||
else:
|
||||
await leader.add_slave(self.config,
|
||||
await suboption.option.name(),
|
||||
await suboption.option.path())
|
||||
variables[leader_name] = leader
|
||||
else:
|
||||
variables[await variable.option.name()] = await variable.value.get()
|
||||
families[await family.option.name()] = CreoleExtra(variables)
|
||||
self.creole_variables_dict[namespace] = CreoleExtra(families)
|
||||
|
||||
def patch_template(self,
|
||||
filename: str):
|
||||
"""Apply patch to a template
|
||||
"""
|
||||
patch_cmd = ['patch', '-d', self.tmp_dir, '-N', '-p1']
|
||||
patch_no_debug = ['-s', '-r', '-', '--backup-if-mismatch']
|
||||
|
||||
# patches variante + locaux
|
||||
for directory in [join(patch_dir, 'variante'), patch_dir]:
|
||||
patch_file = join(directory, f'{filename}.patch')
|
||||
if isfile(patch_file):
|
||||
log.info(_("Patching template '{filename}' with '{patch_file}'"))
|
||||
ret = call(patch_cmd + patch_no_debug + ['-i', patch_file])
|
||||
if ret:
|
||||
patch_cmd_err = ' '.join(patch_cmd + ['-i', patch_file])
|
||||
log.error(_(f"Error applying patch: '{patch_file}'\nTo reproduce and fix this error {patch_cmd_err}"))
|
||||
copy(filename, self.tmp_dir)
|
||||
|
||||
def prepare_template(self,
|
||||
filename: str):
|
||||
"""Prepare template source file
|
||||
"""
|
||||
log.info(_("Copy template: '{filename}' -> '{self.tmp_dir}'"))
|
||||
copy(filename, self.tmp_dir)
|
||||
self.patch_template(filename)
|
||||
|
||||
def process(self,
|
||||
destfilename: str,
|
||||
filevar: Dict,
|
||||
variable: Any):
|
||||
"""Process a cheetah template
|
||||
"""
|
||||
# full path of the destination file
|
||||
log.info(_(f"Cheetah processing: '{destfilename}'"))
|
||||
try:
|
||||
cheetah_template = CheetahTemplate(join(self.tmp_dir,
|
||||
filevar['source']),
|
||||
self.creole_variables_dict,
|
||||
self.eosfunc,
|
||||
destfilename,
|
||||
variable)
|
||||
data = str(cheetah_template)
|
||||
except CheetahNotFound as err:
|
||||
varname = err.args[0][13:-1]
|
||||
raise TemplateError(_(f"Error: unknown variable used in template {destfilename} : {varname}"))
|
||||
except Exception as err:
|
||||
raise TemplateError(_(f"Error while instantiating template {destfilename}: {err}"))
|
||||
|
||||
with open(destfilename, 'w') as file_h:
|
||||
file_h.write(data)
|
||||
|
||||
def instance_file(self,
|
||||
filevar: Dict,
|
||||
systemd_rights: list) -> None:
|
||||
"""Run templatisation on one file
|
||||
"""
|
||||
log.info(_("Instantiating file '{filename}'"))
|
||||
filenames = filevar['name']
|
||||
if 'variable' in filevar:
|
||||
variable = filevar['variable']
|
||||
else:
|
||||
variable = None
|
||||
if not isinstance(filenames, list):
|
||||
filenames = [filenames]
|
||||
if variable:
|
||||
variable = [variable]
|
||||
for idx, filename in enumerate(filenames):
|
||||
destfilename = join(self.dest_dir,
|
||||
filename[1:])
|
||||
makedirs(dirname(destfilename), exist_ok=True)
|
||||
if variable:
|
||||
var = variable[idx]
|
||||
else:
|
||||
var = None
|
||||
self.process(destfilename,
|
||||
filevar,
|
||||
var)
|
||||
systemd_rights.append(f'C {filename} {filevar["mode"]} {filevar["owner"]} {filevar["group"]} - -')
|
||||
systemd_rights.append(f'z {filename} - - - - -')
|
||||
|
||||
async def instance_files(self) -> None:
|
||||
"""Run templatisation on all files
|
||||
"""
|
||||
for option in await self.config.option.list(type='all'):
|
||||
namespace = await option.option.name()
|
||||
if namespace in ['services', 'actions']:
|
||||
continue
|
||||
elif namespace == 'creole':
|
||||
await self.load_eole_variables_creole(option)
|
||||
else:
|
||||
await self.load_eole_variables(namespace,
|
||||
option)
|
||||
for template in listdir(self.distrib_dir):
|
||||
self.prepare_template(join(self.distrib_dir, template))
|
||||
systemd_rights = []
|
||||
for service_obj in await self.config.option('services').list('all'):
|
||||
for fills in await service_obj.list('all'):
|
||||
if await fills.option.name() == 'files':
|
||||
for fill_obj in await fills.list('all'):
|
||||
fill = await fill_obj.value.dict()
|
||||
filename = fill['source']
|
||||
distib_file = join(self.distrib_dir, filename)
|
||||
if not isfile(distib_file):
|
||||
raise FileNotFound(_(f"File {distib_file} does not exist."))
|
||||
if fill.get('activate', False):
|
||||
self.instance_file(fill,
|
||||
systemd_rights)
|
||||
else:
|
||||
log.debug(_("Instantiation of file '{filename}' disabled"))
|
||||
|
||||
with open(join(self.dest_dir, 'rougail.conf'), 'w') as fh:
|
||||
fh.write('\n'.join(systemd_rights))
|
||||
fh.write('\n')
|
||||
|
||||
|
||||
async def generate(config: Config,
|
||||
eosfunc_file: str,
|
||||
distrib_dir: str,
|
||||
tmp_dir: str,
|
||||
dest_dir: str) -> None:
|
||||
engine = CreoleTemplateEngine(config,
|
||||
eosfunc_file,
|
||||
distrib_dir,
|
||||
tmp_dir,
|
||||
dest_dir)
|
||||
await engine.instance_files()
|
23
src/rougail/utils.py
Normal file
23
src/rougail/utils.py
Normal file
@ -0,0 +1,23 @@
|
||||
"""
|
||||
utilitaires créole
|
||||
"""
|
||||
import unicodedata
|
||||
from .i18n import _
|
||||
|
||||
|
||||
def normalize_family(family_name: str,
|
||||
check_name: bool=True,
|
||||
allow_dot: bool=False) -> str:
|
||||
"""replace space, accent, uppercase, ... by valid character
|
||||
"""
|
||||
family_name = family_name.replace('-', '_')
|
||||
if not allow_dot:
|
||||
family_name = family_name.replace('.', '_')
|
||||
family_name = family_name.replace(' ', '_')
|
||||
nfkd_form = unicodedata.normalize('NFKD', family_name)
|
||||
family_name = ''.join([c for c in nfkd_form if not unicodedata.combining(c)])
|
||||
family_name = family_name.lower()
|
||||
if check_name and family_name == 'containers':
|
||||
raise ValueError(_(f'"{family_name}" is a forbidden family name'))
|
||||
return family_name
|
||||
|
@ -1,4 +1,4 @@
|
||||
from tiramisu import valid_not_equal, valid_ip_netmask
|
||||
from tiramisu import valid_not_equal, valid_ip_netmask, calc_value
|
||||
|
||||
def calc_val(*args, **kwargs):
|
||||
pass
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<containers>
|
||||
<container name="tata">
|
||||
</container>
|
||||
</containers>
|
||||
</creole>
|
||||
<rougail>
|
||||
<services>
|
||||
<service name="tata">
|
||||
</service>
|
||||
</services>
|
||||
</rougail>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<family name="containers">
|
||||
<family name="container0" doc="tata">
|
||||
<family name="services">
|
||||
<family name="service0" doc="tata">
|
||||
<property>basic</property>
|
||||
</family>
|
||||
</family>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="général">
|
||||
@ -20,6 +20,6 @@
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1 +1 @@
|
||||
{"creole.general.mode_conteneur_actif": "non", "creole.general.module_instancie": "non"}
|
||||
{"creole.general.mode_conteneur_actif": "non", "creole.general.module_instancie": "non"}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="général">
|
||||
@ -20,6 +20,6 @@
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1 +1 @@
|
||||
{"creole.general.mode_conteneur_actif": "non", "creole.general.module_instancie": "non"}
|
||||
{"creole.general.mode_conteneur_actif": "non", "creole.general.module_instancie": "non"}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="général">
|
||||
@ -17,6 +17,6 @@
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1 +1 @@
|
||||
{"creole.general.mode_conteneur_actif": "non"}
|
||||
{"creole.general.mode_conteneur_actif": "non"}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="général">
|
||||
@ -17,6 +17,6 @@
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1 +1 @@
|
||||
{"creole.general.mode_conteneur_actif": "non"}
|
||||
{"creole.general.mode_conteneur_actif": "non"}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="général">
|
||||
@ -18,6 +18,6 @@
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="général">
|
||||
@ -20,6 +20,6 @@
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1 +1 @@
|
||||
{"creole.general.without_type": "non"}
|
||||
{"creole.general.without_type": "non"}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="général">
|
||||
@ -17,6 +17,6 @@
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="général">
|
||||
@ -17,6 +17,6 @@
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name='général'>
|
||||
@ -18,6 +18,6 @@
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="general">
|
||||
@ -17,12 +17,12 @@
|
||||
|
||||
<constraints>
|
||||
<auto name="calc_val" target="mode_conteneur_actif">
|
||||
<param type="eole">mode_conteneur_actif1</param>
|
||||
<param type="variable">mode_conteneur_actif1</param>
|
||||
</auto>
|
||||
</constraints>
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1 +1 @@
|
||||
{"creole.general.mode_conteneur_actif1": "non"}
|
||||
{"creole.general.mode_conteneur_actif1": "non"}
|
||||
|
@ -12,7 +12,7 @@
|
||||
<property>mandatory</property>
|
||||
<property>normal</property>
|
||||
<value name="calc_val" type="calculation">
|
||||
<param transitive="False" type="eole">creole.general.mode_conteneur_actif1</param>
|
||||
<param transitive="False" type="variable">creole.general.mode_conteneur_actif1</param>
|
||||
</value>
|
||||
</variable>
|
||||
<variable doc="No change" multi="False" name="mode_conteneur_actif1" type="choice">
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="general">
|
||||
@ -22,6 +22,6 @@
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1 +1 @@
|
||||
{"creole.general.mode_conteneur_actif1": "non"}
|
||||
{"creole.general.mode_conteneur_actif1": "non"}
|
||||
|
22
tests/flattener_dicos/01base_multi/00-base.xml
Normal file
22
tests/flattener_dicos/01base_multi/00-base.xml
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<rougail>
|
||||
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="general">
|
||||
<variable name="mode_conteneur_actif" type="oui/non" description="Redefine description" hidden="True" multi="True">
|
||||
<value>non</value>
|
||||
</variable>
|
||||
</family>
|
||||
<separators/>
|
||||
</variables>
|
||||
|
||||
<constraints>
|
||||
</constraints>
|
||||
|
||||
<help/>
|
||||
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
19
tests/flattener_dicos/01base_multi/result/00-base.xml
Normal file
19
tests/flattener_dicos/01base_multi/result/00-base.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<family doc="" name="creole">
|
||||
<family doc="general" name="general">
|
||||
<property>normal</property>
|
||||
<variable doc="Redefine description" multi="True" name="mode_conteneur_actif" type="choice">
|
||||
<choice type="string">oui</choice>
|
||||
<choice type="string">non</choice>
|
||||
<property>force_default_on_freeze</property>
|
||||
<property>frozen</property>
|
||||
<property>hidden</property>
|
||||
<property>mandatory</property>
|
||||
<property>normal</property>
|
||||
<value type="string">non</value>
|
||||
</variable>
|
||||
</family>
|
||||
<separators/>
|
||||
</family>
|
||||
</creole>
|
22
tests/flattener_dicos/01base_submulti/00-base.xml
Normal file
22
tests/flattener_dicos/01base_submulti/00-base.xml
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<rougail>
|
||||
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="general">
|
||||
<variable name="mode_conteneur_actif" type="oui/non" description="Redefine description" hidden="True" submulti="True">
|
||||
<value>non</value>
|
||||
</variable>
|
||||
</family>
|
||||
<separators/>
|
||||
</variables>
|
||||
|
||||
<constraints>
|
||||
</constraints>
|
||||
|
||||
<help/>
|
||||
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
19
tests/flattener_dicos/01base_submulti/result/00-base.xml
Normal file
19
tests/flattener_dicos/01base_submulti/result/00-base.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<family doc="" name="creole">
|
||||
<family doc="general" name="general">
|
||||
<property>normal</property>
|
||||
<variable doc="Redefine description" multi="submulti" name="mode_conteneur_actif" type="choice">
|
||||
<choice type="string">oui</choice>
|
||||
<choice type="string">non</choice>
|
||||
<property>force_default_on_freeze</property>
|
||||
<property>frozen</property>
|
||||
<property>hidden</property>
|
||||
<property>mandatory</property>
|
||||
<property>normal</property>
|
||||
<value type="string">non</value>
|
||||
</variable>
|
||||
</family>
|
||||
<separators/>
|
||||
</family>
|
||||
</creole>
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="general">
|
||||
@ -20,12 +20,12 @@
|
||||
|
||||
<constraints>
|
||||
<fill name="calc_val" target="mode_conteneur_actif">
|
||||
<param type="eole">mode_conteneur_actif1</param>
|
||||
<param type="variable">mode_conteneur_actif1</param>
|
||||
</fill>
|
||||
</constraints>
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1 +1 @@
|
||||
{"creole.general.mode_conteneur_actif": null, "creole.general.mode_conteneur_actif1": "non", "creole.general.module_instancie": "non"}
|
||||
{"creole.general.mode_conteneur_actif": null, "creole.general.mode_conteneur_actif1": "non", "creole.general.module_instancie": "non"}
|
||||
|
@ -12,7 +12,7 @@
|
||||
<property>basic</property>
|
||||
<property expected="oui" inverse="True" source="creole.general.module_instancie" type="calculation">auto_frozen</property>
|
||||
<value name="calc_val" type="calculation">
|
||||
<param transitive="False" type="eole">creole.general.mode_conteneur_actif1</param>
|
||||
<param transitive="False" type="variable">creole.general.mode_conteneur_actif1</param>
|
||||
</value>
|
||||
</variable>
|
||||
<variable doc="No change" multi="False" name="mode_conteneur_actif1" type="choice">
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="general">
|
||||
@ -17,12 +17,12 @@
|
||||
|
||||
<constraints>
|
||||
<fill name="calc_val" target="mode_conteneur_actif">
|
||||
<param type="eole">mode_conteneur_actif1</param>
|
||||
<param type="variable">mode_conteneur_actif1</param>
|
||||
</fill>
|
||||
</constraints>
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1 +1 @@
|
||||
{"creole.general.mode_conteneur_actif": null, "creole.general.mode_conteneur_actif1": "non"}
|
||||
{"creole.general.mode_conteneur_actif": null, "creole.general.mode_conteneur_actif1": "non"}
|
||||
|
@ -10,7 +10,7 @@
|
||||
<property>mandatory</property>
|
||||
<property>basic</property>
|
||||
<value name="calc_val" type="calculation">
|
||||
<param transitive="False" type="eole">creole.general.mode_conteneur_actif1</param>
|
||||
<param transitive="False" type="variable">creole.general.mode_conteneur_actif1</param>
|
||||
</value>
|
||||
</variable>
|
||||
<variable doc="No change" multi="False" name="mode_conteneur_actif1" type="choice">
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="general">
|
||||
@ -17,12 +17,12 @@
|
||||
|
||||
<constraints>
|
||||
<fill name="calc_val" target="mode_conteneur_actif">
|
||||
<param type="eole">mode_conteneur_actif1</param>
|
||||
<param type="variable">mode_conteneur_actif1</param>
|
||||
</fill>
|
||||
</constraints>
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1 +1 @@
|
||||
{"creole.general.mode_conteneur_actif1": "non"}
|
||||
{"creole.general.mode_conteneur_actif1": "non"}
|
||||
|
@ -12,7 +12,7 @@
|
||||
<property>mandatory</property>
|
||||
<property>normal</property>
|
||||
<value name="calc_val" type="calculation">
|
||||
<param transitive="False" type="eole">creole.general.mode_conteneur_actif1</param>
|
||||
<param transitive="False" type="variable">creole.general.mode_conteneur_actif1</param>
|
||||
</value>
|
||||
</variable>
|
||||
<variable doc="No change" multi="False" name="mode_conteneur_actif1" type="choice">
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="Général">
|
||||
@ -17,12 +17,12 @@
|
||||
|
||||
<constraints>
|
||||
<fill name="calc_val" target="mode_conteneur_actif">
|
||||
<param type="eole">mode_conteneur_actif1</param>
|
||||
<param type="variable">mode_conteneur_actif1</param>
|
||||
</fill>
|
||||
</constraints>
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1 +1 @@
|
||||
{"creole.general.mode_conteneur_actif1": "non"}
|
||||
{"creole.general.mode_conteneur_actif1": "non"}
|
||||
|
@ -12,7 +12,7 @@
|
||||
<property>mandatory</property>
|
||||
<property>normal</property>
|
||||
<value name="calc_val" type="calculation">
|
||||
<param transitive="False" type="eole">creole.general.mode_conteneur_actif1</param>
|
||||
<param transitive="False" type="variable">creole.general.mode_conteneur_actif1</param>
|
||||
</value>
|
||||
</variable>
|
||||
<variable doc="No change" multi="False" name="mode_conteneur_actif1" type="choice">
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="general" mode="basic">
|
||||
@ -15,12 +15,12 @@
|
||||
|
||||
<constraints>
|
||||
<fill name="calc_val" target="mode_conteneur_actif">
|
||||
<param type="eole">mode_conteneur_actif1</param>
|
||||
<param type="variable">mode_conteneur_actif1</param>
|
||||
</fill>
|
||||
</constraints>
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1 +1 @@
|
||||
{"creole.general.mode_conteneur_actif": null, "creole.general.mode_conteneur_actif1": "non"}
|
||||
{"creole.general.mode_conteneur_actif": null, "creole.general.mode_conteneur_actif1": "non"}
|
||||
|
@ -7,7 +7,7 @@
|
||||
<property>mandatory</property>
|
||||
<property>expert</property>
|
||||
<value name="calc_val" type="calculation">
|
||||
<param transitive="False" type="eole">creole.general.mode_conteneur_actif1</param>
|
||||
<param transitive="False" type="variable">creole.general.mode_conteneur_actif1</param>
|
||||
</value>
|
||||
</variable>
|
||||
<variable doc="No change" multi="False" name="mode_conteneur_actif1" type="choice">
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="general">
|
||||
@ -21,6 +21,6 @@
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1 +1 @@
|
||||
{"creole.general.mode_conteneur_actif1": "non"}
|
||||
{"creole.general.mode_conteneur_actif1": "non"}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="general">
|
||||
@ -17,14 +17,14 @@
|
||||
|
||||
<constraints>
|
||||
<fill name="calc_val" target="mode_conteneur_actif">
|
||||
<param type="eole" optional="True">mode_conteneur_actif4</param>
|
||||
<param type="eole">mode_conteneur_actif1</param>
|
||||
<param type="eole" optional="True">mode_conteneur_actif3</param>
|
||||
<param type="variable" optional="True">mode_conteneur_actif4</param>
|
||||
<param type="variable">mode_conteneur_actif1</param>
|
||||
<param type="variable" optional="True">mode_conteneur_actif3</param>
|
||||
</fill>
|
||||
</constraints>
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1 +1 @@
|
||||
{"creole.general.mode_conteneur_actif1": "non"}
|
||||
{"creole.general.mode_conteneur_actif1": "non"}
|
||||
|
@ -12,7 +12,7 @@
|
||||
<property>mandatory</property>
|
||||
<property>normal</property>
|
||||
<value name="calc_val" type="calculation">
|
||||
<param transitive="False" type="eole">creole.general.mode_conteneur_actif1</param>
|
||||
<param transitive="False" type="variable">creole.general.mode_conteneur_actif1</param>
|
||||
</value>
|
||||
</variable>
|
||||
<variable doc="No change" multi="False" name="mode_conteneur_actif1" type="choice">
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="general">
|
||||
@ -19,6 +19,6 @@
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="general">
|
||||
@ -19,6 +19,6 @@
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="général">
|
||||
@ -22,6 +22,6 @@
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="général">
|
||||
@ -25,6 +25,6 @@
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1 +1 @@
|
||||
{"creole.general.autosavevar": null}
|
||||
{"creole.general.autosavevar": null}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="general">
|
||||
@ -22,6 +22,6 @@
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1 +1 @@
|
||||
{"creole.general.mode_conteneur_actif": "b", "creole.general.int": null}
|
||||
{"creole.general.mode_conteneur_actif": "b", "creole.general.int": null}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="general">
|
||||
@ -19,12 +19,12 @@
|
||||
<constraints>
|
||||
<check name="valid_entier" target="int">
|
||||
<param name="mini">0</param>
|
||||
<param name="maxi" type="eole">int2</param>
|
||||
<param name="maxi" type="variable">int2</param>
|
||||
</check>
|
||||
</constraints>
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1 +1 @@
|
||||
{"creole.general.mode_conteneur_actif": "b", "creole.general.int2": 100, "creole.general.int": null}
|
||||
{"creole.general.mode_conteneur_actif": "b", "creole.general.int2": 100, "creole.general.int": null}
|
||||
|
@ -16,7 +16,7 @@
|
||||
<variable doc="No change" multi="False" name="int" type="number">
|
||||
<check name="valid_entier" warnings_only="False">
|
||||
<param name="mini" type="string">0</param>
|
||||
<param name="maxi" type="eole">creole.general.int2</param>
|
||||
<param name="maxi" type="variable">creole.general.int2</param>
|
||||
</check>
|
||||
<property>normal</property>
|
||||
</variable>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="general">
|
||||
@ -16,16 +16,16 @@
|
||||
|
||||
<constraints>
|
||||
<check name="valid_differ" target="int">
|
||||
<param type="eole" optional="True">int2</param>
|
||||
<param type="variable" optional="True">int2</param>
|
||||
</check>
|
||||
<check name="valid_differ" target="int">
|
||||
<param type="eole" optional="True">int3</param>
|
||||
<param type="variable" optional="True">int3</param>
|
||||
</check>
|
||||
|
||||
</constraints>
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1 +1 @@
|
||||
{"creole.general.mode_conteneur_actif": "b", "creole.general.int": null, "creole.general.int2": null}
|
||||
{"creole.general.mode_conteneur_actif": "b", "creole.general.int": null, "creole.general.int2": null}
|
||||
|
@ -10,7 +10,7 @@
|
||||
</variable>
|
||||
<variable doc="No change" multi="False" name="int" type="number">
|
||||
<check name="valid_not_equal" warnings_only="False">
|
||||
<param type="eole">creole.general.int2</param>
|
||||
<param type="variable">creole.general.int2</param>
|
||||
</check>
|
||||
<check name="valid_not_equal" warnings_only="False"/>
|
||||
<property>normal</property>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<creole>
|
||||
<rougail>
|
||||
|
||||
<containers/>
|
||||
<services/>
|
||||
|
||||
<variables>
|
||||
<family name="general">
|
||||
@ -17,12 +17,12 @@
|
||||
|
||||
<constraints>
|
||||
<check name="valid_differ" target="mode_conteneur_actif">
|
||||
<param type="eole">mode_conteneur_actif1</param>
|
||||
<param type="variable">mode_conteneur_actif1</param>
|
||||
</check>
|
||||
</constraints>
|
||||
|
||||
<help/>
|
||||
|
||||
</creole>
|
||||
</rougail>
|
||||
<!-- vim: ts=4 sw=4 expandtab
|
||||
-->
|
||||
|
@ -1 +1 @@
|
||||
{"creole.general.mode_conteneur_actif": "oui", "creole.general.mode_conteneur_actif1": "non"}
|
||||
{"creole.general.mode_conteneur_actif": "oui", "creole.general.mode_conteneur_actif1": "non"}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user