def mock_puppetdb_default_nodes(mocker): node_list = [ Node('_', 'node-unreported', report_timestamp='2013-08-01T09:57:00.000Z', latest_report_hash='1234567', catalog_timestamp='2013-08-01T09:57:00.000Z', facts_timestamp='2013-08-01T09:57:00.000Z', status_report='unreported'), Node('_', 'node-changed', report_timestamp='2013-08-01T09:57:00.000Z', latest_report_hash='1234567', catalog_timestamp='2013-08-01T09:57:00.000Z', facts_timestamp='2013-08-01T09:57:00.000Z', status_report='changed'), Node('_', 'node-failed', report_timestamp='2013-08-01T09:57:00.000Z', latest_report_hash='1234567', catalog_timestamp='2013-08-01T09:57:00.000Z', facts_timestamp='2013-08-01T09:57:00.000Z', status_report='failed'), Node('_', 'node-noop', report_timestamp='2013-08-01T09:57:00.000Z', latest_report_hash='1234567', catalog_timestamp='2013-08-01T09:57:00.000Z', facts_timestamp='2013-08-01T09:57:00.000Z', status_report='noop'), Node('_', 'node-unchanged', report_timestamp='2013-08-01T09:57:00.000Z', latest_report_hash='1234567', catalog_timestamp='2013-08-01T09:57:00.000Z', facts_timestamp='2013-08-01T09:57:00.000Z', status_report='unchanged'), ] return mocker.patch.object(app.puppetdb, 'nodes', return_value=iter(node_list))
def test_with_cached_catalog_status(self): node1 = Node('_', 'node', cached_catalog_status='explicitly_requested') node2 = Node('_', 'node', cached_catalog_status='on_failure') node3 = Node('_', 'node', cached_catalog_status='not_used') assert node1.name == 'node' assert node1.cached_catalog_status == 'explicitly_requested' assert node2.name == 'node' assert node2.cached_catalog_status == 'on_failure' assert node3.name == 'node' assert node3.cached_catalog_status == 'not_used'
def nodes(self, name=None, query=None): """Query for nodes by either name or query. If both aren't provided this will return a list of all nodes. :param name: (optional) :type name: :obj:`None` or :obj:`string` :param query: (optional) :type query: :obj:`None` or :obj:`string` :returns: A generator yieling Nodes. :rtype: :class:`pypuppetdb.types.Node` """ nodes = self._query('nodes', path=name, query=query) # If we happen to only get one node back it # won't be inside a list so iterating over it # goes boom. Therefor we wrap a list around it. if type(nodes) == dict: log.debug("Request returned a single node.") nodes = [ nodes, ] for node in nodes: yield Node( self, node['name'], deactivated=node['deactivated'], report_timestamp=node['report_timestamp'], catalog_timestamp=node['catalog_timestamp'], facts_timestamp=node['facts_timestamp'], )
def test_apiv4_with_unchanged_status(self): node = Node( '_', 'node', status='unchanged', report_environment='development', catalog_environment='development', facts_environment='development', report_timestamp='2013-08-01T09:57:00.000Z', catalog_timestamp='2013-08-01T09:57:00.000Z', facts_timestamp='2013-08-01T09:57:00.000Z', ) assert node.name == 'node' assert node.deactivated is False assert node.expired is False assert node.report_environment == 'development' assert node.catalog_environment == 'development' assert node.facts_environment == 'development' assert node.report_timestamp == \ json_to_datetime('2013-08-01T09:57:00.000Z') assert node.facts_timestamp == \ json_to_datetime('2013-08-01T09:57:00.000Z') assert node.catalog_timestamp == \ json_to_datetime('2013-08-01T09:57:00.000Z') assert node.status == 'unchanged' assert str(node) == str('node') assert unicode(node) == unicode('node') assert repr(node) == str('<Node: node>')
def test_with_status_unreported(self): node = Node( '_', 'node', report_timestamp='2013-08-01T09:57:00.000Z', catalog_timestamp='2013-08-01T09:57:00.000Z', facts_timestamp='2013-08-01T09:57:00.000Z', status='unreported', unreported_time='0d 5h 20m', ) assert node.name == 'node' assert node.deactivated is False assert node.expired is False assert node.report_timestamp == \ json_to_datetime('2013-08-01T09:57:00.000Z') assert node.facts_timestamp == \ json_to_datetime('2013-08-01T09:57:00.000Z') assert node.catalog_timestamp == \ json_to_datetime('2013-08-01T09:57:00.000Z') assert node.status is 'unreported' assert node.unreported_time is '0d 5h 20m' assert str(node) == str('node') assert unicode(node) == unicode('node') assert repr(node) == str('<Node: node>')
def test_apiv4_with_failed_noop_status(self): node = Node( '_', 'node', status_report='failed', noop=True, noop_pending=False, report_environment='development', catalog_environment='development', facts_environment='development', report_timestamp='2013-08-01T09:57:00.000Z', catalog_timestamp='2013-08-01T09:57:00.000Z', facts_timestamp='2013-08-01T09:57:00.000Z', ) assert node.name == 'node' assert node.deactivated is False assert node.expired is False assert node.report_environment == 'development' assert node.catalog_environment == 'development' assert node.facts_environment == 'development' assert node.report_timestamp == \ json_to_datetime('2013-08-01T09:57:00.000Z') assert node.facts_timestamp == \ json_to_datetime('2013-08-01T09:57:00.000Z') assert node.catalog_timestamp == \ json_to_datetime('2013-08-01T09:57:00.000Z') assert node.status == 'failed' assert str(node) == str('node') assert str(node) == str('node') assert repr(node) == str('<Node: node>')
def test_expired(self): node = Node( '_', 'node', expired='2013-08-01T09:57:00.000Z', ) assert node.name == 'node' assert node.expired == json_to_datetime('2013-08-01T09:57:00.000Z') assert str(node) == str('node') assert unicode(node) == unicode('node') assert repr(node) == str('<Node: node>')
def test_deactivated(self): node = Node( '_', 'node', deactivated='2013-08-01T09:57:00.000Z', ) assert node.name == 'node' assert node.deactivated == \ json_to_datetime('2013-08-01T09:57:00.000Z') assert str(node) == str('node') assert str(node) == str('node') assert repr(node) == str('<Node: node>')
def test_node(): node1 = Node( '_', 'node1.puppet.board', report_timestamp='2013-08-01T09:57:00.000Z', catalog_timestamp='2013-08-01T09:57:00.000Z', facts_timestamp='2013-08-01T09:57:00.000Z', status='unreported', unreported_time='0d 5h 20m', ) node2 = Node( '_', 'node2.puppet.board', deactivated='2013-08-01T09:57:00.000Z', report_timestamp=None, catalog_timestamp=None, facts_timestamp=None, ) assert node1.name == 'node1.puppet.board' assert node1.deactivated is False assert node1.report_timestamp is not None assert node1.facts_timestamp is not None assert node1.catalog_timestamp is not None assert node1.status is 'unreported' assert node1.unreported_time is '0d 5h 20m' assert str(node1) == str('node1.puppet.board') assert repr(node1) == str('<Node: node1.puppet.board>') assert node2.name == 'node2.puppet.board' assert node2.deactivated is not False assert node2.report_timestamp is None assert node2.catalog_timestamp is None assert node2.facts_timestamp is None assert str(node2) == str('node2.puppet.board') assert repr(node2) == str('<Node: node2.puppet.board>')
def test_without_status(self): node = Node( '_', 'node', report_timestamp='2013-08-01T09:57:00.000Z', catalog_timestamp='2013-08-01T09:57:00.000Z', facts_timestamp='2013-08-01T09:57:00.000Z', ) assert node.name == 'node' assert node.deactivated is False assert node.report_timestamp is not None assert node.facts_timestamp is not None assert node.catalog_timestamp is not None assert str(node) == str('node') assert unicode(node) == unicode('node') assert repr(node) == str('<Node: node>')
def mock_puppetdb_default_nodes(mocker): timestamp = '2013-08-01T09:57:00.000Z' report_hash = '1234567' transaction = '7890' version = '3.8.5' node_list = [ Node('_', 'node-%s' % status, report_timestamp=timestamp, latest_report_hash=report_hash, catalog_timestamp=timestamp, facts_timestamp=timestamp, status_report=status, report=Report('_', 'node-%s', report_hash, timestamp, timestamp, timestamp, version, '6', version, transaction)) for status in ['failed', 'changed', 'unchanged', 'noop', 'unreported'] ] return mocker.patch.object(app.puppetdb, 'nodes', return_value=iter(node_list))
def test_without_status(self): node = Node( '_', 'node', report_timestamp='2013-08-01T09:57:00.000Z', catalog_timestamp='2013-08-01T09:57:00.000Z', facts_timestamp='2013-08-01T09:57:00.000Z', ) assert node.name == 'node' assert node.deactivated is False assert node.expired is False assert node.report_timestamp == \ json_to_datetime('2013-08-01T09:57:00.000Z') assert node.facts_timestamp == \ json_to_datetime('2013-08-01T09:57:00.000Z') assert node.catalog_timestamp == \ json_to_datetime('2013-08-01T09:57:00.000Z') assert str(node) == str('node') assert str(node) == str('node') assert repr(node) == str('<Node: node>')
def nodes(self, unreported=2, with_status=False, **kwargs): """Query for nodes by either name or query. If both aren't provided this will return a list of all nodes. This method also fetches the nodes status and event counts of the latest report from puppetdb. :param with_status: (optional) include the node status in the\ returned nodes :type with_status: :bool: :param unreported: (optional) amount of hours when a node gets marked as unreported :type unreported: :obj:`None` or integer :param \*\*kwargs: The rest of the keyword arguments are passed to the _query function :returns: A generator yieling Nodes. :rtype: :class:`pypuppetdb.types.Node` """ nodes = self._query('nodes', **kwargs) now = datetime.datetime.utcnow() # If we happen to only get one node back it # won't be inside a list so iterating over it # goes boom. Therefor we wrap a list around it. if type(nodes) == dict: nodes = [ nodes, ] if with_status: latest_events = self.event_counts(query=EqualsOperator( "latest_report?", True), summarize_by='certname') for node in nodes: node['status_report'] = None node['events'] = None if with_status: status = [ s for s in latest_events if s['subject']['title'] == node['certname'] ] try: node['status_report'] = node['latest_report_status'] if status: node['events'] = status[0] except KeyError: if status: node['events'] = status = status[0] if status['successes'] > 0: node['status_report'] = 'changed' if status['noops'] > 0: node['status_report'] = 'noop' if status['failures'] > 0: node['status_report'] = 'failed' else: node['status_report'] = 'unchanged' # node report age if node['report_timestamp'] is not None: try: last_report = json_to_datetime( node['report_timestamp']) last_report = last_report.replace(tzinfo=None) unreported_border = now - timedelta(hours=unreported) if last_report < unreported_border: delta = (now - last_report) node['unreported'] = True node['unreported_time'] = '{0}d {1}h {2}m'.format( delta.days, int(delta.seconds / 3600), int((delta.seconds % 3600) / 60)) except AttributeError: node['unreported'] = True if not node['report_timestamp']: node['unreported'] = True yield Node(self, name=node['certname'], deactivated=node['deactivated'], expired=node['expired'], report_timestamp=node['report_timestamp'], catalog_timestamp=node['catalog_timestamp'], facts_timestamp=node['facts_timestamp'], status_report=node['status_report'], noop=node.get('latest_report_noop'), noop_pending=node.get('latest_report_noop_pending'), events=node['events'], unreported=node.get('unreported'), unreported_time=node.get('unreported_time'), report_environment=node['report_environment'], catalog_environment=node['catalog_environment'], facts_environment=node['facts_environment'], latest_report_hash=node.get('latest_report_hash'), cached_catalog_status=node.get('cached_catalog_status'))
def nodes(self, name=None, query=None, unreported=2, with_status=False): """Query for nodes by either name or query. If both aren't provided this will return a list of all nodes. This method also fetches the nodes status and event counts of the latest report from puppetdb. :param name: (optional) :type name: :obj:`None` or :obj:`string` :param query: (optional) :type query: :obj:`None` or :obj:`string` :param with_status: (optional) include the node status in the\ returned nodes :type with_status: :bool: :param unreported: (optional) amount of hours when anode gets marked as unreported :type unreported: :obj:`None` or integer :returns: A generator yieling Nodes. :rtype: :class:`pypuppetdb.types.Node` """ nodes = self._query('nodes', path=name, query=query) # If we happen to only get one node back it # won't be inside a list so iterating over it # goes boom. Therefor we wrap a list around it. if type(nodes) == dict: nodes = [ nodes, ] if with_status: latest_events = self._query('event-counts', query='["=","latest-report?",true]', summarize_by='certname') for node in nodes: node['unreported_time'] = None node['status'] = None if with_status: status = [ s for s in latest_events if s['subject']['title'] == node['name'] ] # node status from events if with_status and status: node['events'] = status = status[0] if status['successes'] > 0: node['status'] = 'changed' if status['failures'] > 0: node['status'] = 'failed' else: node['status'] = 'unchanged' node['events'] = None # node report age if with_status and node['report_timestamp'] is not None: try: last_report = json_to_datetime(node['report_timestamp']) last_report = last_report.replace(tzinfo=None) now = datetime.utcnow() unreported_border = now - timedelta(hours=unreported) if last_report < unreported_border: delta = (datetime.utcnow() - last_report) node['status'] = 'unreported' node['unreported_time'] = '{0}d {1}h {2}m'.format( delta.days, int(delta.seconds / 3600), int((delta.seconds % 3600) / 60)) except AttributeError: node['status'] = 'unreported' if not node['report_timestamp']: node['status'] = 'unreported' yield Node(self, node['name'], deactivated=node['deactivated'], report_timestamp=node['report_timestamp'], catalog_timestamp=node['catalog_timestamp'], facts_timestamp=node['facts_timestamp'], status=node['status'], events=node['events'], unreported_time=node['unreported_time'])
def test_with_latest_report_hash(self): node = Node('_', 'node', latest_report_hash='hash#1') assert node.name == 'node' assert node.latest_report_hash == 'hash#1'