def test_override_os(self, mock_load_os_plugins): mock_load_os_plugins.return_value = _os_plugin_list o = OSSupport() o.override_os(("ubuntu", "precise")) os = o.current_os assert(os.name == "ubuntu") assert(os.all_names == ["ubuntu", "debian"]) assert(os.get_version() == "precise") assert(os.get_all_tuples("precise") == [("ubuntu", "precise"), ("debian", None)]) assert(os.default_installer == "apt") assert(os.get_core_installers("precise", {}) == ["apt"])
def test_get_current_os(self, mock_load_os_plugins): mock_load_os_plugins.return_value = _os_plugin_list # get_current_os calls detect_os if no os not set yet o1 = OSSupport() o1.detect_os() os1 = o1.current_os o2 = OSSupport() os2 = o2.current_os assert(os1.get_tuple() == os2.get_tuple())
def test_default_installer_name(self, mock_load_os_plugins): mock_load_os_plugins.return_value = _os_plugin_list o = OSSupport() expected = _default_installers result = o.get_default_installer_names() if expected != result: print("result:") pprint(result) print("expected:") pprint(expected) assert(expected == result)
def main(args=None): args = command_handle_args(args, definition) try: # prepare arguments filepath = os.path.abspath(os.path.expanduser(args.rules_file)) # parse rules file with open(filepath, 'rb') as f: data = to_str(f.read()) rules = load_yaml(data) rules = expand_rules(rules) verify_rules_dict(rules) # compact rules compacted = compact_rules(rules, OSSupport().get_default_installer_names()) # output result dump = dump_yaml(compacted) if args.write: with open(filepath, 'wb') as f: f.write(to_bytes(dump)) else: info(dump) except (KeyboardInterrupt, EOFError): sys.exit(1)
def setup_os(self): """Create `OSSupport` and detect or override OS depending on config. :raises xylem.os_support.UnsupportedOsError: if OS override was invalid and detection failed :raises xylem.os_support.UnsupportedOSVersionError: if override version is not valid for override OS """ self.os_support = OSSupport(self.config.disabled_plugins.os) if self.config.os_override is None: self.os_support.detect_os() info_v("detected OS [%s]" % self.get_os_string()) else: info_v("overriding OS to [%s:%s]" % self.config.os_override) self.os_support.override_os(self.config.os_override) if self.config.os_override[1] is None: info_v("detected OS version [%s]" % self.get_os_string()) self.get_os().options = self.config.os_options
def test_current_os_throws(self, mock_load_os_plugins): mock_load_os_plugins.return_value = _os_plugin_list o = OSSupport() # override invalid os with self.assertRaises(UnsupportedOSError): o.override_os(("foo", "bar")) print("invalid os 'foo' did not raise") with self.assertRaises(UnsupportedOSVersionError): o.override_os(("ubuntu", "bar")) print("invalid ubuntu version 'bar' did not raise") # fake failed detection o.os_plugins = [] with self.assertRaises(UnsupportedOSError): o.detect_os() print("failed detection did not raise")
def test_detect_version_only(self): # test that the actual OS is detected (no exception is raised) o = OSSupport() name, version = o.current_os.get_tuple() o = OSSupport() o.override_os((name, None)) os = o.current_os assert(name == os.name) assert(version == os.get_version())
class InstallerContext(object): """Manages the context of OS and installers for xylem. It combines OS plugins, installer plugins and user settings to manage the current OS and installers to be used. :ivar dict config: config dictionary used; e.g. for os override, os options, installer options :ivar OSSupport os_support: os support object managing current (or override) os; is set by :meth:`setup_os` :ivar installer_plugins: list of all known installer objects, independent of the current OS :type installer_plugins: `list` of `Installer` :ivar core_installers: list of the core installer objects for the current os; is set by :meth:`setup_installers` :type core_installers: `list` of `Installer` :ivar additional_installers: list of the additional installer objects for the current os; is set by :meth:`setup_installers` :type additional_installers: `list` of `Installer` """ def __init__(self, config=None, os_support=None, setup_installers=True): if config is None: config = get_config() self.config = config if os_support is None: self.setup_os() else: self.os_support = os_support self.installer_plugins = load_installer_plugins( self.config.disabled_plugins.installer) if setup_installers: self.setup_installers() else: self.core_installers = [] self.additional_installers = [] def setup_os(self): """Create `OSSupport` and detect or override OS depending on config. :raises xylem.os_support.UnsupportedOsError: if OS override was invalid and detection failed :raises xylem.os_support.UnsupportedOSVersionError: if override version is not valid for override OS """ self.os_support = OSSupport(self.config.disabled_plugins.os) if self.config.os_override is None: self.os_support.detect_os() info_v("detected OS [%s]" % self.get_os_string()) else: info_v("overriding OS to [%s:%s]" % self.config.os_override) self.os_support.override_os(self.config.os_override) if self.config.os_override[1] is None: info_v("detected OS version [%s]" % self.get_os_string()) self.get_os().options = self.config.os_options def get_os(self): """Get the current OS plugin object. :rtype xylem.os_support.OS: the current OS object :raises xylem.os_support.UnsupportedOsError: if OS was not detected correctly """ return self.os_support.current_os def get_os_tuple(self): """Get the current OS (name,version) tuple. :return: (os_name, os_version) :rtype: ``(str,str)`` :raises xylem.os_support.UnsupportedOsError: if OS was not detected correctly """ return self.get_os().get_tuple() def get_os_string(self): """Get the cuurent OS name and version as ``'name:version'`` string. :rtype: `str` :raises xylem.os_support.UnsupportedOsError: if OS was not detected correctly """ return "%s:%s" % self.get_os_tuple() def get_default_installer_name(self): """Get name of default installer for current OS. :rtype: `str` """ return self.os_support.current_os.default_installer @property def installers(self): """Get list of core and additional installers. :meth:`setup_installers` needs to be called beforehand. :rtype: `list` of `Installer` """ return self.core_installers + self.additional_installers @property def installer_names(self): """Get list of names for core and additional installers. :meth:`setup_installers` needs to be called beforehand. :rtype: `list` of `str` """ return [i.name for i in self.installers] @property def core_installer_names(self): """Get list of names for core installers. :meth:`setup_installers` needs to be called beforehand. :rtype: `list` of `str` """ return [i.name for i in self.core_installers] @property def additional_installer_names(self): """Get list of names for additional installers. :meth:`setup_installers` needs to be called beforehand. :rtype: `list` of `str` """ return [i.name for i in self.additional_installers] @property def installer_plugin_names(self): """Get list of names for all known installers. :rtype: `list` of `str` """ return [i.name for i in self.installer_plugins] def lookup_installer(self, name): """Get installer object by name. :param str name: name of the installer :return: if found, installer object, else ``None`` :rtype: `Installer` or ``None`` """ for inst in self.installer_plugins: if inst.name == name: return inst return None def setup_installers(self): """For current os, setup configured installers. Installers are set based on the current os, user config and installer plugins. """ os = self.get_os() os_tuple = os.get_tuple() _, os_version = os_tuple self.core_installers = [] self.additional_installers = [] # 1. Go through all installers and set options from config for inst in self.installer_plugins: inst.options = self.config.installer_options.get(inst.name, {}) # 2. setup core installers from config or OS plugin if self.config.core_installers is not None: core_installer_names = self.config.core_installers info_v("setting up core installers from config: '{}'". format(", ".join(core_installer_names))) else: core_installer_names = os.get_core_installers(os_version, os.options) info_v("setting up core installers from os plugin: '{}'". format(", ".join(core_installer_names))) for name in core_installer_names: inst = self.lookup_installer(name) if inst is None: error("ignoring core installer '{}'; according plugin was not " "found".format(name)) else: self.core_installers.append(inst) # 3. Go through all installers and check if they should be used # as additional installers for the current OS. if self.config.use_additional_installers: for inst in self.installer_plugins: if inst not in self.core_installers and \ inst.use_as_additional_installer(os_tuple): self.additional_installers.append(inst) info_v("Using additional installers: '{}'".format( ", ".join([i.name for i in self.additional_installers])))
def test_detect_running_os(self): # test that the actual OS is detected (no exception is raised) o = OSSupport() name, version = o.current_os.get_tuple() assert(name is not None) assert(version is not None)
class InstallerContext(object): """Manages the context of OS and installers for xylem. It combines OS plugins, installer plugins and user settings to manage the current OS and installers to be used. :ivar dict config: config dictionary used; e.g. for os override, os options, installer options :ivar OSSupport os_support: os support object managing current (or override) os; is set by :meth:`setup_os` :ivar installer_plugins: list of all known installer objects, independent of the current OS :type installer_plugins: `list` of `Installer` :ivar core_installers: list of the core installer objects for the current os; is set by :meth:`setup_installers` :type core_installers: `list` of `Installer` :ivar additional_installers: list of the additional installer objects for the current os; is set by :meth:`setup_installers` :type additional_installers: `list` of `Installer` """ def __init__(self, config=None, os_support=None, setup_installers=True): if config is None: config = get_config() self.config = config if os_support is None: self.setup_os() else: self.os_support = os_support self.installer_plugins = load_installer_plugins( self.config.disabled_plugins.installer) if setup_installers: self.setup_installers() else: self.core_installers = [] self.additional_installers = [] def setup_os(self): """Create `OSSupport` and detect or override OS depending on config. :raises xylem.os_support.UnsupportedOsError: if OS override was invalid and detection failed :raises xylem.os_support.UnsupportedOSVersionError: if override version is not valid for override OS """ self.os_support = OSSupport(self.config.disabled_plugins.os) if self.config.os_override is None: self.os_support.detect_os() info_v("detected OS [%s]" % self.get_os_string()) else: info_v("overriding OS to [%s:%s]" % self.config.os_override) self.os_support.override_os(self.config.os_override) if self.config.os_override[1] is None: info_v("detected OS version [%s]" % self.get_os_string()) self.get_os().options = self.config.os_options def get_os(self): """Get the current OS plugin object. :rtype xylem.os_support.OS: the current OS object :raises xylem.os_support.UnsupportedOsError: if OS was not detected correctly """ return self.os_support.current_os def get_os_tuple(self): """Get the current OS (name,version) tuple. :return: (os_name, os_version) :rtype: ``(str,str)`` :raises xylem.os_support.UnsupportedOsError: if OS was not detected correctly """ return self.get_os().get_tuple() def get_os_string(self): """Get the cuurent OS name and version as ``'name:version'`` string. :rtype: `str` :raises xylem.os_support.UnsupportedOsError: if OS was not detected correctly """ return "%s:%s" % self.get_os_tuple() def get_default_installer_name(self): """Get name of default installer for current OS. :rtype: `str` """ return self.os_support.current_os.default_installer @property def installers(self): """Get list of core and additional installers. :meth:`setup_installers` needs to be called beforehand. :rtype: `list` of `Installer` """ return self.core_installers + self.additional_installers @property def installer_names(self): """Get list of names for core and additional installers. :meth:`setup_installers` needs to be called beforehand. :rtype: `list` of `str` """ return [i.name for i in self.installers] @property def core_installer_names(self): """Get list of names for core installers. :meth:`setup_installers` needs to be called beforehand. :rtype: `list` of `str` """ return [i.name for i in self.core_installers] @property def additional_installer_names(self): """Get list of names for additional installers. :meth:`setup_installers` needs to be called beforehand. :rtype: `list` of `str` """ return [i.name for i in self.additional_installers] @property def installer_plugin_names(self): """Get list of names for all known installers. :rtype: `list` of `str` """ return [i.name for i in self.installer_plugins] def lookup_installer(self, name): """Get installer object by name. :param str name: name of the installer :return: if found, installer object, else ``None`` :rtype: `Installer` or ``None`` """ for inst in self.installer_plugins: if inst.name == name: return inst return None def setup_installers(self): """For current os, setup configured installers. Installers are set based on the current os, user config and installer plugins. """ os = self.get_os() os_tuple = os.get_tuple() _, os_version = os_tuple self.core_installers = [] self.additional_installers = [] # 1. Go through all installers and set options from config for inst in self.installer_plugins: inst.options = self.config.installer_options.get(inst.name, {}) # 2. setup core installers from config or OS plugin if self.config.core_installers is not None: core_installer_names = self.config.core_installers info_v("setting up core installers from config: '{}'".format( ", ".join(core_installer_names))) else: core_installer_names = os.get_core_installers( os_version, os.options) info_v("setting up core installers from os plugin: '{}'".format( ", ".join(core_installer_names))) for name in core_installer_names: inst = self.lookup_installer(name) if inst is None: error("ignoring core installer '{}'; according plugin was not " "found".format(name)) else: self.core_installers.append(inst) # 3. Go through all installers and check if they should be used # as additional installers for the current OS. if self.config.use_additional_installers: for inst in self.installer_plugins: if inst not in self.core_installers and \ inst.use_as_additional_installer(os_tuple): self.additional_installers.append(inst) info_v("Using additional installers: '{}'".format(", ".join( [i.name for i in self.additional_installers])))