Source code for rceapp

# This is a simple class which reads the rceapp.yml installed by Puppet
# or any other configuration management.

from yaml import load, dump

[docs]class RCEAppGlobalError(Exception): """ This is a self-defined exception such that I can output a useful error message which says that a stanza in the YAML is missing the default value heading. Variables: cfg: path to the RCEApp YML configuration value: KeyError exception object """ def __init__(self, cfg, value): self.value = value self.cfg = cfg def __str__(self): return repr('A stanza in %s is missing the global value heading.' %(self.cfg))
[docs]class RCEAppDefaultError(Exception): """ This is a self-defined exception such that I can output a useful error message which says that at least one version of an app should have the default set to True Variables: cfg: path to the RCEApp YML configuration value: KeyError exception object """ def __init__(self, cfg, value): self.value = value self.cfg = cfg def __str__(self): return repr("Either at least one version requires the default\ boolean in %s, two versions have the default boolean, or default is\ not set to true or false." %(self.cfg))
[docs]class RCEAppGlobalMemoryError(Exception): """ This is a self-defined exception such that I can output a useful error message which says that a default stanza in the provided YML is missing a default memory assignment. Variables: cfg: path to the RCEApp YML configuration value: KeyError exception object """ def __init__(self, cfg, value): self.value = value self.cfg = cfg def __str__(self): return repr('A stanza in %s is missing a global memory value.' %(self.cfg))
[docs]class RCEAppGlobalCpuError(Exception): """ This is a self-defined exception such that I can output a useful error message which says that a default stanza in the provided YML is missing a default cpu assignment. Variables: cfg: path to the RCEApp YML configuration value: KeyError exception object """ def __init__(self, cfg, value): self.value = value self.cfg = cfg def __str__(self): return repr('A stanza in %s is missing a cpu value.' %(self.cfg))
[docs]class RCEAppIntError(Exception): """ This is a self-defined exception such that I can output a useful error message which notifies you if you accidentially used non-integer characters in the memory field. Variables: cfg: path to the RCEApp YML configuration value: KeyError exception object """ def __init__(self, cfg, value): self.value = value self.cfg = cfg def __str__(self): return repr('Default memory/cpu values in %s must be integers.' %(self.cfg))
[docs]class rceapp: """ This is the rceapp class which manipulates an RCEApp YAML Variables: cfg = path to RCEApp YML configuration """ def __init__(self, cfg): self.cfg = cfg try: with file(cfg, 'r') as _data_stream: self.data = load(_data_stream) except: raise self.__validate() def __str__(self): """ When you call str on an rceapp object, it just returns the yaml as a hash """ return dump(self.data) def __validate(self): """ Validates the loaded yml data self.data to ensure that each app has a default section at least. If you're not familiar with map and lambda, basically this is a loop that applies the lambda function over self.apps() which returns an array. """ try: map(lambda app: self.data[app]['global'], self.apps()) except KeyError as e: raise RCEAppGlobalError(self.cfg, e) # Checks whether default stanzas contain default memory try: map(lambda app: self.data[app]['global']['memory'], self.apps()) except KeyError as e: raise RCEAppGlobalMemoryError(self.cfg, e) # Checks whether default stanzas contain default cpu count try: map(lambda app: self.data[app]['global']['cpu'], self.apps()) except KeyError as e: raise RCEAppGlobalCpuError(self.cfg, e) # Checks whether default memory is an integer, which it should be. try: map(lambda app: self.data[app]['global']['memory'] + 1, self.apps()) except TypeError as e: raise RCEAppIntError(self.cfg, e) # Checks whether default cpu is an integer, which it should be. try: map(lambda app: self.data[app]['global']['cpu'] + 1, self.apps()) except TypeError as e: raise RCEAppIntError(self.cfg, e) # Checks whether at least one version is default, no more than one # default key per entry, and that value is a boolean. default_map = map(lambda app: map(lambda version: self.data[app][version]['default'] if self.data[app][version].has_key('default') else None, self.versions(app)), self.apps()) sorted_count = sorted(map(lambda x: x.count(True), default_map)) if sorted_count[0] == 0: raise RCEAppDefaultError(self.cfg, "No default.") elif sorted_count[-1] > 1: raise RCEAppDefaultError(self.cfg, "Too many defaults.")
[docs] def apps(self): """apps() returns the keys of the data loaded from the yaml""" return self.data.keys()
[docs] def versions(self,app): """ versions() returns all the versions listed for an app, specified by the app argument, in an array. """ return filter( lambda key: key != 'global', self.data[app].keys() )
[docs] def app_version_exists(self,app,version=None): if version: return (True if app in self.apps() and version in self.versions(app) else False) else: return (True if app in self.apps() else False)
[docs] def supports_cpu_adjustable(self, app): return self.supports_adjustable(app, 'cpu')
[docs] def supports_memory_adjustable(self, app): return self.supports_adjustable(app, 'memory')
[docs] def supports_adjustable(self, app, label): assert label in ['memory', 'cpu'] try: return self.data[app]['global']["supports_{0}_adjustable". format(label)] except: return True
[docs] def command(self,app,version=None): """ command() returns the full path of an application given its version and application name as arguments. """ _version = version if version else self.get_default_version(app) return self.data[app][_version]['command']
[docs] def args(self,app,version=None): """ args() returns a string of arguments for an given application's version. """ _version = version if version else self.get_default_version(app) try: return ' '.join(self.data[app][_version]['args']) except: try: return ' '.join(self.data[app]['global']['args']) except: return None
[docs] def get_default_version(self, app): _versions = map (lambda version: version if self.is_default(app,version) else None, self.versions(app)) return sorted(_versions)[-1]
[docs] def is_default(self,app,version): """ Returns True if app,version is the default version for the app. """ try: return self.data[app][version]['default'] except: return False
[docs] def memory(self,app,version=None): """ memory() returns the default memory requirements of an application's specified version. If a memory default is not specified for that particular version, it grabs the default memory from the default stanza for that app. """ _version = version if version else self.get_default_version(app) try: return self.data[app][_version]['memory'] except: return self.data[app]['global']['memory']
[docs] def icon(self, app, version=None): """ icon() returns the icon path for an application. If no icon, return none. """ _version = version if version else self.get_default_version(app) try: return self.data[app][_version]['icon'] except: try: return self.data[app]['global']['icon'] except: return None
[docs] def cpu(self,app,version=None): """ cpu() returns the default CPU count requirement of an application's specified version. If a cpu default is not specified for that particular version, it grabs the default memory from the default stanza for that app. """ _version = version if version else self.get_default_version(app) try: return self.data[app][_version]['cpu'] except: return self.data[app]['global']['cpu']