Skip to content

Commit

Permalink
Refactoring classes
Browse files Browse the repository at this point in the history
  • Loading branch information
Adrien Delle Cave committed Jul 4, 2018
1 parent a732c04 commit 301f7b9
Show file tree
Hide file tree
Showing 11 changed files with 856 additions and 700 deletions.
2 changes: 1 addition & 1 deletion bin/covenant
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ __license__ = """
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
__version__ = '0.0.6.26'
__version__ = '0.0.6.27'

# TODO: load Python logging configuration (using standard logging.config)

Expand Down
147 changes: 147 additions & 0 deletions covenant/classes/collect.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# -*- coding: utf-8 -*-
"""covenant collect"""

__author__ = "Adrien DELLE CAVE <adc@doowan.net>"
__license__ = """
Copyright (C) 2018 doowan
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA..
"""

import copy
import logging

from covenant.classes.exceptions import CovenantTargetFailed
from covenant.classes.filters import CovenantNoResult

LOG = logging.getLogger('covenant.collect')


class CovenantCollect(object):
def __init__(self,
name,
metric,
method = None,
value = None,
default = None,
labels = None,
value_tasks = None,
on_fail = None,
on_noresult = None):
self.name = name
self.metric = metric
self.method = method
self.value = value
self.default = default
self.labels = labels
self.value_tasks = value_tasks

self.on_fail = self._on(on_fail)
self.on_noresult = self._on(on_noresult)

def _on(self, cfg):
default = {'value': None,
'remove': True}

if isinstance(cfg, dict):
default['remove'] = False
default.update(cfg)
elif cfg not in (None, 'remove'):
default['remove'] = False

return default.copy()

def remove(self, val = True):
setattr(self.metric, '_removed', bool(val))
return self

def removed(self):
return getattr(self.metric, '_removed', False)

def __call__(self, data):
self.remove(False)
if not isinstance(data, CovenantTargetFailed) \
and self.value is not None:
data = self.value

data = copy.copy(data)

if self.labels:
for label in self.labels:
label.task_label(data)
label.task_value(data, self.value_tasks)
elif self.value_tasks:
if isinstance(data, CovenantTargetFailed):
if self.on_fail['remove']:
self.remove(True)
return
data = copy.copy(self.on_fail['value'])
else:
for task in self.value_tasks:
if isinstance(data, CovenantNoResult):
if self.on_noresult['remove']:
self.remove(True)
return
data = self.on_noresult['value']
break
data = task(value = data)

if isinstance(data, CovenantTargetFailed):
if self.on_fail['remove']:
self.remove(True)
return
data = self.on_fail['value']

if self.default is not None and data is None:
data = self.default

if not self.labels:
try:
getattr(self.metric, self.method)(data)
except Exception, e:
LOG.exception("metric: %r, data: %r, error: %r", self.name, data, e)
raise
del data
return

has_label = False

for label in self.labels:
if label.removed() or not label.labelvalues:
continue

has_label = True

for labelvalue in label.labelvalues:
method = getattr(self.metric.labels(
**{labelvalue.labelname: labelvalue.labelvalue}),
self.method)

try:
method(labelvalue.get())
except Exception, e:
LOG.exception("metric: %r, labelname: %r, labelvalue: %r, data: %r, error: %r",
self.name,
labelvalue.labelname,
labelvalue.labelvalue,
labelvalue.get(),
e)
raise

if not has_label:
self.remove(True)

del data

5 changes: 1 addition & 4 deletions covenant/classes/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import signal
import yaml

from covenant.classes.exceptions import CovenantConfigurationError
from covenant.classes.plugins import ENDPOINTS, PLUGINS
from dwho.config import parse_conf, stop, DWHO_THREADS
from dwho.classes.libloader import DwhoLibLoader
Expand All @@ -37,10 +38,6 @@
LOG = logging.getLogger('covenant.config')


class CovenantConfigurationError(Exception):
pass


def import_file(filepath, config_dir = None, xvars = {}):
if config_dir and not filepath.startswith(os.path.sep):
filepath = os.path.join(config_dir, filepath)
Expand Down
169 changes: 169 additions & 0 deletions covenant/classes/controls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
# -*- coding: utf-8 -*-
"""covenant controls"""

__author__ = "Adrien DELLE CAVE <adc@doowan.net>"
__license__ = """
Copyright (C) 2018 doowan
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA..
"""

import copy
import logging
import re

from covenant.classes.label import CovenantLabelValue

LOG = logging.getLogger('covenant.controls')


class CovenantCtrlLabelize(object):
@staticmethod
def _to_remove(key, kargs):
r = False

if 'include' in kargs:
r = key not in lkargs['include']

if 'exclude' in kargs and key in kargs['exclude']:
r = key in kargs['exclude']

if 'include_regex' in kargs:
r = not re.match(kargs['include_regex'], key)

if 'exclude_regex' in kargs:
r = bool(re.match(kargs['exclude_regex'], key))

return r

@classmethod
def dict(cls, *largs, **lkargs):
def g(*args, **kwargs):
r = []
kargs = copy.copy(kwargs)

if not isinstance(kwargs['value'], dict):
return kwargs['value']

if 'key' in lkargs and 'value' in lkargs:
metricvalue = kwargs['value'].get(lkargs['value'])
if metricvalue is None:
metricvalue = lkargs.get('default')
kargs['value'] = CovenantLabelValue(labelvalue = kwargs['value'][lkargs['key']],
metricvalue = metricvalue,
remove = cls._to_remove(kwargs['value'][lkargs['key']], lkargs))
return kargs['value']

xlen = len(kwargs['value'])

for k, v in kwargs['value'].iteritems():
kargs['value'] = CovenantLabelValue(labelvalue = k,
metricvalue = v,
remove = cls._to_remove(k, lkargs))

if xlen == 1:
return kargs['value']
else:
r.append(kargs['value'])

return r
return g


class CovenantCtrlLoop(object):
@classmethod
def iter(cls, f = None):
def g(*args, **kwargs):
r = []
kargs = copy.copy(kwargs)

if not hasattr(kwargs['value'], '__iter__'):
if not f:
return kargs['value']
return f(*args, **kargs)

for v in kwargs['value']:
kargs['value'] = copy.copy(v)
if not f:
r.append(kargs['value'])
else:
r.append(f(*args, **kargs))

return r
return g

@classmethod
def dict(cls, f = None):
def g(*args, **kwargs):
r = []
kargs = copy.copy(kwargs)

if not isinstance(kwargs['value'], dict):
if not f:
return kwargs['value']
return f(*args, **kargs)

for k, v in kwargs['value'].iteritems():
kargs['key'] = k
kargs['value'] = copy.copy(v)
if not f:
r.append({'key': kargs['key'], 'value': kargs['value']})
else:
r.append(f(*args, **kargs))

return r
return g

@classmethod
def dict_keys(cls, f = None):
def g(*args, **kwargs):
r = []
kargs = copy.copy(kwargs)

if not hasattr(kwargs['value'], 'iterkeys'):
if not f:
return kargs['value']
return f(*args, **kargs)

for k in kwargs['value'].iterkeys():
kargs['value'] = k
if not f:
r.append(kargs['value'])
else:
r.append(f(*args, **kargs))

return r
return g

@classmethod
def dict_values(cls, f = None):
def g(*args, **kwargs):
r = []
kargs = copy.copy(kwargs)

if not isinstance(kwargs['value'], dict):
if not f:
return kargs['value']
return f(*args, **kargs)

for v in kwargs['value'].itervalues():
kargs['value'] = copy.copy(v)
if not f:
r.append(kargs['value'])
else:
r.append(f(*args, **kargs))

return r
return g
37 changes: 37 additions & 0 deletions covenant/classes/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
"""covenant exceptions"""

__author__ = "Adrien DELLE CAVE <adc@doowan.net>"
__license__ = """
Copyright (C) 2018 doowan
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA..
"""

import logging

LOG = logging.getLogger('covenant.exceptions')


class CovenantConfigurationError(Exception):
pass


class CovenantTargetFailed(Exception):
def __init__(self, message = None, args = None):
if isinstance(message, Exception):
return Exception.__init__(self, message.message, message.args)
else:
return Exception.__init__(self, message, args)

0 comments on commit 301f7b9

Please sign in to comment.