예제 #1
0
    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
예제 #2
0
파일: server.py 프로젝트: charles-l/pyinfra
    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
예제 #3
0
    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
예제 #4
0
파일: files.py 프로젝트: weakish/pyinfra
    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
예제 #5
0
    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
예제 #6
0
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,
        )
예제 #7
0
    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
예제 #8
0
    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
예제 #9
0
    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
예제 #10
0
    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
예제 #11
0
    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
예제 #12
0
파일: mysql.py 프로젝트: morrison12/pyinfra
    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
예제 #13
0
    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
예제 #14
0
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),
        )
예제 #15
0
    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
예제 #16
0
    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
예제 #17
0
파일: files.py 프로젝트: morrison12/pyinfra
    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
예제 #18
0
파일: files.py 프로젝트: vindarel/pyinfra
    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
예제 #19
0
 def test_try_int_fail(self):
     assert try_int('hello') == 'hello'
예제 #20
0
 def test_try_int_number(self):
     assert try_int('1') == 1
예제 #21
0
 def test_try_int_number(self):
     self.assertEqual(try_int('1'), 1)
예제 #22
0
 def test_try_int_fail(self):
     self.assertEqual(try_int('hello'), 'hello')