Exemplo n.º 1
0
 def test_greater_operator(self):
     assert str(GreaterOperator("uptime", 150))\
         == '[">", "uptime", 150]'
     assert str(GreaterOperator("end_time", '2016-05-11T23:22:48.709Z'))\
         == '[">", "end_time", "2016-05-11T23:22:48.709Z"]'
     assert str(GreaterOperator(['parameter', 'version'], 4.0))\
         == '[">", ["parameter", "version"], 4.0]'
     assert str(GreaterOperator("report_timestamp",
                                datetime.datetime(2016, 6, 11)))\
         == '[">", "report_timestamp", "2016-06-11 00:00:00"]'
Exemplo n.º 2
0
    def test_not_operator(self):
        op = NotOperator()
        op.add(EqualsOperator("operatingsystem", "CentOS"))

        assert str(op) == '["not", ["=", "operatingsystem", "CentOS"]]'
        assert repr(op) == 'Query: ["not", ["=", "operatingsystem", "CentOS"]]'
        assert str(op) == '["not", ["=", "operatingsystem", "CentOS"]]'

        with pytest.raises(APIError):
            op.add(GreaterOperator("operatingsystemmajrelease", 6))
        with pytest.raises(APIError):
            op.add([EqualsOperator("architecture", "x86_64"),
                    GreaterOperator("operatingsystemmajrelease", 6)])
Exemplo n.º 3
0
def _puppetdb_nodes(rules, master_id, master_address):
    if "facts" not in rules or not rules["facts"]:
        return set()

    if rules["match_type"] == "ALL":
        operator = AndOperator()
    else:
        operator = OrOperator()
    for fact_rule in rules["facts"]:
        rule_op = fact_rule["operator"]
        lhs = ["fact", fact_rule["fact"]]
        rhs = fact_rule["value"]
        if rule_op == "=":
            operator.add(EqualsOperator(lhs, rhs))
        elif rule_op == "!=":
            notop = NotOperator()
            notop.add(EqualsOperator(lhs, rhs))
            operator.add(notop)
        elif rule_op == "~":
            operator.add(RegexOperator(lhs, rhs))
        elif rule_op == "!~":
            notop = NotOperator()
            notop.add(RegexOperator(lhs, rhs))
            operator.add(notop)
        elif rule_op == ">":
            operator.add(GreaterOperator(lhs, rhs))
        elif rule_op == ">=":
            operator.add(GreaterEqualOperator(lhs, rhs))
        elif rule_op == "<":
            operator.add(LessOperator(lhs, rhs))
        elif rule_op == "<=":
            operator.add(LessEqualOperator(lhs, rhs))

    query_str = str(operator).replace("'", '"')

    cert_instance = CertsClass(master_id)
    cert_path = cert_instance.get_cert()
    private_key_path = cert_instance.get_key()

    req = requests.get(
        f"https://{master_address}:8081/pdb/meta/v1/version",
        verify=False,
        cert=(cert_path, private_key_path),
    )
    if req.status_code == 404:
        # PuppetDB <= 2.x
        nodes_uri = f"https://{master_address}:8081/v4/nodes?query={query_str}"
    else:
        # PuppetDB >= 3.x
        nodes_uri = (
            f"https://{master_address}:8081/pdb/query/v4/nodes?query={query_str}"
        )
    # Fetch the matching nodes
    req = requests.get(nodes_uri,
                       verify=False,
                       cert=(cert_path, private_key_path))
    return {node["certname"] for node in req.json()}
Exemplo n.º 4
0
def main():
    """main entry point"""
    args = get_args()
    logging.basicConfig(level=get_log_level(args.verbose))

    failed_nodes = []
    pdb = connect()
    nodes = defaultdict(dict)

    max_age = datetime.utcnow() - timedelta(hours=args.max_age)

    extract = ExtractOperator()
    extract.add_field(['certname', FunctionOperator('count'), 'status'])
    extract.add_group_by(['certname', 'status'])
    extract.add_query(GreaterOperator('receive_time', max_age.isoformat()))

    # pypuppetdb does have a `reports` method which wraps `_query`.  however it yields
    # results of type pypuppetdb.Report which expects a number of parameters e.g. hash
    # to be present in the result payload.  however we don't extract theses values and
    # therefore have to resort to the more powerful private method
    reports = pdb._query('reports', query=extract)  # pylint: disable=protected-access

    for report in reports:
        nodes[report['certname']][report['status']] = report['count']

    if args.dev:
        failed_nodes = [hostname for hostname, node in nodes.items()
                        if not node.get('unchanged', 0)]
    else:
        for fqdn, node in nodes.items():
            # skip hosts with no unchanged reports:
            if node.get('unchanged', 0):
                continue
            # skip staging servers:
            # - hostname starting labstest*
            # - hostname ending dev or dev\d{4}
            # - hostname ending test or test\d{4}
            if (fqdn.startswith('labtest')
                    or search(r'(:?dev|test)(:?\d{4})?$', fqdn.split('.')[0]) is not None):
                logger.debug('%s: Skipping staging host', fqdn)
                continue
            failed_nodes.append(fqdn)

    if len(failed_nodes) >= args.critical:
        print('CRITICAL: the following ({}) node(s) change every puppet run: {}'.format(
            len(failed_nodes), ', '.join(failed_nodes)))
        return 2
    if len(failed_nodes) >= args.warning:
        print('WARNING: the following ({}) node(s) change every puppet run: {}'.format(
            len(failed_nodes), ', '.join(failed_nodes)))
        return 1

    print('OK: all nodes running as expected')
    return 0
Exemplo n.º 5
0
    def test_or_operator(self):
        op = OrOperator()
        op.add(EqualsOperator("operatingsystem", "CentOS"))
        op.add([EqualsOperator("architecture", "x86_64"),
                GreaterOperator("operatingsystemmajrelease", 6)])

        assert str(op) == '["or", ["=", "operatingsystem", "CentOS"], '\
            '["=", "architecture", "x86_64"], '\
            '[">", "operatingsystemmajrelease", 6]]'
        assert repr(op) == 'Query: ["or", '\
            '["=", "operatingsystem", "CentOS"], '\
            '["=", "architecture", "x86_64"], '\
            '[">", "operatingsystemmajrelease", 6]]'
        assert str(op) == '["or", ["=", "operatingsystem", "CentOS"], ' \
                          '["=", "architecture", "x86_64"], '\
            '[">", "operatingsystemmajrelease", 6]]'

        with pytest.raises(APIError):
            op.add({"query1": '["=", "catalog_environment", "production"]'})
def main():
    """main entry point"""
    args = get_args()
    logging.basicConfig(level=get_log_level(args.verbose))

    pdb = connect()
    nodes = defaultdict(dict)

    max_age = datetime.utcnow() - timedelta(hours=args.max_age)

    extract = ExtractOperator()
    extract.add_field(['certname', FunctionOperator('count'), 'status'])
    extract.add_group_by(['certname', 'status'])
    extract.add_query(GreaterOperator('receive_time', max_age.isoformat()))

    # pypuppetdb does have a `reports` method which wraps `_query`.  however it yields
    # results of type pypuppetdb.Report which expects a number of parameters e.g. hash
    # to be present in the result payload.  however we don't extract theses values and
    # therefore have to resort to the more powerful private method
    reports = pdb._query('reports', query=extract)  # pylint: disable=protected-access

    for report in reports:
        nodes[report['certname']][report['status']] = report['count']
    failed_nodes = [
        hostname for hostname, node in nodes.items()
        if not node.get('unchanged', 0)
    ]

    if len(failed_nodes) >= args.critical:
        print(
            'CRITICAL: the following ({}) node(s) change every puppet run: {}'.
            format(len(failed_nodes), ', '.join(failed_nodes)))
        return 2
    if len(failed_nodes) >= args.warning:
        print(
            'WARNING: the following ({}) node(s) change every puppet run: {}'.
            format(len(failed_nodes), ', '.join(failed_nodes)))
        return 1

    print('OK: all nodes running as expected')
    return 0
Exemplo n.º 7
0
    def test_with_add_query(self):
        op = ExtractOperator()

        op.add_field(['certname', 'fact_environment', 'catalog_environment'])

        with pytest.raises(APIError):
            op.add_query({'less': 42, 'greater': 50})

        op.add_query(EqualsOperator('domain', 'example.com'))

        assert repr(op) == 'Query: ["extract", '\
            '["certname", "fact_environment", "catalog_environment"], '\
            '["=", "domain", "example.com"]]'
        assert str(op) == '["extract", '\
            '["certname", "fact_environment", "catalog_environment"], '\
            '["=", "domain", "example.com"]]'
        assert str(op) == '["extract", ' \
                          '["certname", "fact_environment", "catalog_environment"], '\
            '["=", "domain", "example.com"]]'

        with pytest.raises(APIError):
            op.add_query(GreaterOperator("processorcount", 1))