def process(output): crons = {} current_comments = [] for line in output: line = line.strip() if not line or line.startswith("#"): current_comments.append(line) continue if line.startswith("@"): special_time, command = line.split(None, 1) crons[command] = { "special_time": special_time, "comments": current_comments, } else: minute, hour, day_of_month, month, day_of_week, command = line.split( None, 5) crons[command] = { "minute": try_int(minute), "hour": try_int(hour), "month": try_int(month), "day_of_month": try_int(day_of_month), "day_of_week": try_int(day_of_week), "comments": current_comments, } current_comments = [] return crons
def process(self, output): parts = {} for part in '\n'.join(output).strip().split('---'): if not part.strip(): continue filename, content = part.strip().split('\n', 1) parts[filename] = content release_info = self.default() if not parts: return release_info temp_root = mkdtemp() try: temp_etc_dir = os.path.join(temp_root, 'etc') os.mkdir(temp_etc_dir) for filename, content in parts.items(): with open(os.path.join(temp_etc_dir, os.path.basename(filename)), 'w') as fp: fp.write(content) parsed = get_distro_info(temp_root) release_meta = {key.upper(): value for key, value in parsed.os_release_info().items()} release_info.update({ 'name': self.name_to_pretty_name.get(parsed.id(), parsed.name()), 'major': try_int(parsed.major_version()), 'minor': try_int(parsed.minor_version()) or None, 'release_meta': release_meta, }) finally: shutil.rmtree(temp_root) return release_info
def process(output): crons = {} current_comments = [] for line in output: line = line.strip() if not line or line.startswith('#'): current_comments.append(line) continue if line.startswith('@'): special_time, command = line.split(' ', 1) crons[command] = { 'special_time': special_time, 'comments': current_comments, } else: minute, hour, day_of_month, month, day_of_week, command = line.split(' ', 5) crons[command] = { 'minute': try_int(minute), 'hour': try_int(hour), 'month': try_int(month), 'day_of_month': try_int(day_of_month), 'day_of_week': try_int(day_of_week), 'comments': current_comments, } current_comments = [] return crons
def process(self, output): stat_bits = output[0].split(None, 7) stat_bits, filename = stat_bits[:-1], stat_bits[-1] data = {} path_type = None for bit in stat_bits: key, value = bit.split('=') if key == 'mode': path_type = FLAG_TO_TYPE[value[0]] value = _parse_mode(value[1:]) elif key == 'size': value = try_int(value) elif key in ('atime', 'mtime', 'ctime'): value = try_int(value) if isinstance(value, int): value = datetime.utcfromtimestamp(value) data[key] = value if path_type != self.type: return False if path_type == 'link': filename, target = filename.split(' -> ') data['link_target'] = target.strip("'") return data
def process(self, output): parts = {} for part in "\n".join(output).strip().split("---"): if not part.strip(): continue try: filename, content = part.strip().split("\n", 1) parts[filename] = content except ValueError: # skip empty files # for instance arch linux as an empty file at /etc/arch-release continue release_info = self.default() if not parts: return release_info temp_root = mkdtemp() try: temp_etc_dir = os.path.join(temp_root, "etc") os.mkdir(temp_etc_dir) for filename, content in parts.items(): with open( os.path.join(temp_etc_dir, os.path.basename(filename)), "w") as fp: fp.write(content) parsed = get_distro_info(temp_root) release_meta = { key.upper(): value for key, value in parsed.os_release_info().items() } # Distro 1.7+ adds this, breaking tests # TODO: fix this! release_meta.pop("RELEASE_CODENAME", None) release_info.update( { "name": self.name_to_pretty_name.get(parsed.id(), parsed.name()), "major": try_int(parsed.major_version()) or None, "minor": try_int(parsed.minor_version()) or None, "release_meta": release_meta, }, ) finally: shutil.rmtree(temp_root) return release_info
def sysctl( key, value, persist=False, persist_file='/etc/sysctl.conf', state=None, host=None, ): ''' Edit sysctl configuration. + key: name of the sysctl setting to ensure + value: the value or list of values the sysctl should be + persist: whether to write this sysctl to the config + persist_file: file to write the sysctl to persist on reboot Example: .. code:: python server.sysctl( name='Change the fs.file-max value', key='fs.file-max', value=100000, persist=True, ) ''' string_value = ( ' '.join(['{0}'.format(v) for v in value]) if isinstance(value, list) else value ) value = ( [try_int(v) for v in value] if isinstance(value, list) else try_int(value) ) existing_value = host.fact.sysctl.get(key) if not existing_value or existing_value != value: yield "sysctl {0}='{1}'".format(key, string_value) host.fact.sysctl[key] = value else: host.noop('sysctl {0} is set to {1}'.format(key, string_value)) if persist: yield files.line( path=persist_file, line='{0}[[:space:]]*=[[:space:]]*{1}'.format(key, string_value), replace='{0} = {1}'.format(key, string_value), state=state, host=host, )
def process(self, output): # Remove the last line of the output (row count) output = output[:-1] rows = parse_columns_and_rows( output, "|", # Remove the "rol" prefix on column names remove_column_prefix="rol", ) users = {} for details in rows: for key, value in list(details.items()): if key in ("oid", "connlimit"): details[key] = try_int(value) if key in ( "super", "inherit", "createrole", "createdb", "canlogin", "replication", "bypassrls", ): details[key] = value == "t" users[details.pop("name")] = details return users
def process(self, output): # Remove the last line of the output (row count) output = output[:-1] rows = parse_columns_and_rows( output, "|", # Remove the "dat" prefix on column names remove_column_prefix="dat", ) databases = {} for details in rows: details["encoding"] = details.pop("pg_encoding_to_char") for key, value in list(details.items()): if key.endswith("id") or key in ( "dba", "tablespace", "connlimit", ): details[key] = try_int(value) if key in ("istemplate", "allowconn"): details[key] = value == "t" databases[details.pop("name")] = details return databases
def process(output): rows = parse_columns_and_rows(output, '\t') users = {} for details in rows: if details.get('Host') is None or details.get('User') is None: continue # pragma: no cover privileges = [] for key, value in list(details.items()): if key.endswith('_priv') and details.pop(key) == 'Y': privileges.append(key.replace('_priv', '')) if key.startswith('max_'): details[key] = try_int(value) if key in ('password_expired', 'is_role'): details[key] = value == 'Y' details['privileges'] = sorted(privileges) # Attach the user in the format user@host users['{0}@{1}'.format( details.pop('User'), details.pop('Host'), )] = details return users
def process(output): sysctls = {} for line in output: key = values = None if '=' in line: key, values = line.split('=', 1) elif ':' in line: key, values = line.split(':', 1) else: continue # pragma: no cover if key and values: key = key.strip() values = values.strip() if re.match(r'^[a-zA-Z0-9_\.\s]+$', values): values = [try_int(item.strip()) for item in values.split()] if len(values) == 1: values = values[0] sysctls[key] = values return sysctls
def process(self, output): # Remove the last line of the output (row count) output = output[:-1] rows = parse_columns_and_rows( output, '|', # Remove the "rol" prefix on column names remove_column_prefix='rol', ) users = {} for details in rows: for key, value in list(details.items()): if key in ('oid', 'connlimit'): details[key] = try_int(value) if key in ( 'super', 'inherit', 'createrole', 'createdb', 'canlogin', 'replication', 'bypassrls', ): details[key] = value == 't' users[details.pop('name')] = details return users
def process(output): rows = parse_columns_and_rows(output, "\t") users = {} for details in rows: if details.get("Host") is None or details.get("User") is None: continue # pragma: no cover privileges = [] for key, value in list(details.items()): if key.endswith("_priv") and details.pop(key) == "Y": privileges.append(key.replace("_priv", "")) if key.startswith("max_"): details[key] = try_int(value) if key in ("password_expired", "is_role"): details[key] = value == "Y" details["privileges"] = sorted(privileges) # Attach the user in the format user@host users[ "{0}@{1}".format( details.pop("User"), details.pop("Host"), ) ] = details return users
def process(self, output): # Remove the last line of the output (row count) output = output[:-1] rows = parse_columns_and_rows( output, '|', # Remove the "dat" prefix on column names remove_column_prefix='dat', ) databases = {} for details in rows: details['encoding'] = details.pop('pg_encoding_to_char') for key, value in list(details.items()): if key.endswith('id') or key in ( 'dba', 'tablespace', 'connlimit', ): details[key] = try_int(value) if key in ('istemplate', 'allowconn'): details[key] = value == 't' databases[details.pop('name')] = details return databases
def sysctl( key, value, persist=False, persist_file="/etc/sysctl.conf", ): """ Edit sysctl configuration. + key: name of the sysctl setting to ensure + value: the value or list of values the sysctl should be + persist: whether to write this sysctl to the config + persist_file: file to write the sysctl to persist on reboot **Example:** .. code:: python server.sysctl( name="Change the fs.file-max value", key="fs.file-max", value=100000, persist=True, ) """ string_value = " ".join(["{0}".format(v) for v in value]) if isinstance( value, list) else value value = [try_int(v) for v in value] if isinstance(value, list) else try_int(value) existing_sysctls = host.get_fact(Sysctl) existing_value = existing_sysctls.get(key) if not existing_value or existing_value != value: yield "sysctl {0}='{1}'".format(key, string_value) existing_sysctls[key] = value else: host.noop("sysctl {0} is set to {1}".format(key, string_value)) if persist: yield from files.line( path=persist_file, line="{0}[[:space:]]*=[[:space:]]*{1}".format(key, string_value), replace="{0} = {1}".format(key, string_value), )
def process(output): crons = {} for line in output: line = line.strip() if not line or line.startswith('#'): continue minute, hour, day_of_month, month, day_of_week, command = line.split( ' ', 5) crons[command] = { 'minute': try_int(minute), 'hour': try_int(hour), 'month': try_int(month), 'day_of_month': try_int(day_of_month), 'day_of_week': try_int(day_of_week), } return crons
def process(self, output): meta = {} for line in output: if '=' in line: key, value = line.split('=') meta[key] = value.strip('"') name = None major = None minor = None if 'ID' in meta and 'VERSION_ID' in meta: name = meta['ID'].title() version_bits = meta['VERSION_ID'].split('.') major = version_bits[0] if len(version_bits) > 1: minor = version_bits[1] else: for line in output: matched = False for regex in self.regexes: matches = re.search(regex, line) if matches: name = matches.group(1) major = matches.group(2) minor = matches.group(3) matched = True break if matched: break release_info = self.default() release_info.update({ 'name': self.name_to_pretty_name.get(name, name), 'major': try_int(major), 'minor': try_int(minor), 'release_meta': meta, }) return release_info
def process(self, output): match = re.match(STAT_REGEX, output[0]) if not match: return None data = {} path_type = None for key, value in ( ("user", match.group(1)), ("group", match.group(2)), ("mode", match.group(3)), ("atime", match.group(4)), ("mtime", match.group(5)), ("ctime", match.group(6)), ("size", match.group(7)), ): if key == "mode": path_type = FLAG_TO_TYPE[value[0]] value = _parse_mode(value[1:]) elif key == "size": value = try_int(value) elif key in ("atime", "mtime", "ctime"): value = try_int(value) if isinstance(value, int): value = datetime.utcfromtimestamp(value) data[key] = value if path_type != self.type: return False if path_type == "link": filename = match.group(8) filename, target = filename.split(" -> ") data["link_target"] = target.strip("'").lstrip("`") return data
def process(self, output): match = re.match(STAT_REGEX, output[0]) if not match: return None data = {} path_type = None for key, value in ( ('user', match.group(1)), ('group', match.group(2)), ('mode', match.group(3)), ('atime', match.group(4)), ('mtime', match.group(5)), ('ctime', match.group(6)), ('size', match.group(7)), ): if key == 'mode': path_type = FLAG_TO_TYPE[value[0]] value = _parse_mode(value[1:]) elif key == 'size': value = try_int(value) elif key in ('atime', 'mtime', 'ctime'): value = try_int(value) if isinstance(value, int): value = datetime.utcfromtimestamp(value) data[key] = value if path_type != self.type: return False if path_type == 'link': filename = match.group(8) filename, target = filename.split(' -> ') data['link_target'] = target.strip("'") return data
def test_try_int_fail(self): assert try_int('hello') == 'hello'
def test_try_int_number(self): assert try_int('1') == 1
def test_try_int_number(self): self.assertEqual(try_int('1'), 1)
def test_try_int_fail(self): self.assertEqual(try_int('hello'), 'hello')