Hello community,
here is the log from the commit of package python-pypuppetdb for
openSUSE:Factory checked in at 2019-09-11 10:36:36
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pypuppetdb (Old)
and /work/SRC/openSUSE:Factory/.python-pypuppetdb.new.7948 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pypuppetdb"
Wed Sep 11 10:36:36 2019 rev:4 rq:729838 version:1.1.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pypuppetdb/python-pypuppetdb.changes
2019-08-28 18:36:36.825271898 +0200
+++
/work/SRC/openSUSE:Factory/.python-pypuppetdb.new.7948/python-pypuppetdb.changes
2019-09-11 10:36:38.515274475 +0200
@@ -1,0 +2,8 @@
+Tue Sep 10 11:49:00 UTC 2019 - Tomáš Chvátal <[email protected]>
+
+- Update to 1.1.0:
+ * deduplicate dependencylist
+ * QueryBuilder.py: Use native data structures for internal representation
+ * Add support for the Command API
+
+-------------------------------------------------------------------
Old:
----
v1.0.0.tar.gz
New:
----
v1.1.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-pypuppetdb.spec ++++++
--- /var/tmp/diff_new_pack.bG7X9O/_old 2019-09-11 10:36:39.403274216 +0200
+++ /var/tmp/diff_new_pack.bG7X9O/_new 2019-09-11 10:36:39.403274216 +0200
@@ -18,7 +18,7 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-pypuppetdb
-Version: 1.0.0
+Version: 1.1.0
Release: 0
Summary: Library to work with PuppetDB's REST API
License: Apache-2.0
++++++ v1.0.0.tar.gz -> v1.1.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pypuppetdb-1.0.0/CHANGELOG.rst
new/pypuppetdb-1.1.0/CHANGELOG.rst
--- old/pypuppetdb-1.0.0/CHANGELOG.rst 2019-05-30 14:11:34.000000000 +0200
+++ new/pypuppetdb-1.1.0/CHANGELOG.rst 2019-08-31 12:32:56.000000000 +0200
@@ -2,6 +2,13 @@
Changelog
#########
+1.1.0
+=====
+
+* deduplicate dependencylist
+* QueryBuilder.py: Use native data structures for internal representation
+* Add support for the Command API, /pdb/cmd/v1. Added _cmd alongside _query to
minimise changes to original code
+
1.0.0
=====
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pypuppetdb-1.0.0/pypuppetdb/QueryBuilder.py
new/pypuppetdb-1.1.0/pypuppetdb/QueryBuilder.py
--- old/pypuppetdb-1.0.0/pypuppetdb/QueryBuilder.py 2019-05-30
14:11:34.000000000 +0200
+++ new/pypuppetdb-1.1.0/pypuppetdb/QueryBuilder.py 2019-08-31
12:32:56.000000000 +0200
@@ -2,6 +2,7 @@
from __future__ import absolute_import
import datetime
+import json
import logging
import sys
@@ -39,31 +40,21 @@
:type value: any
"""
def __init__(self, operator, field, value):
- if isinstance(field, (str, unicode)):
- field = '"{0}"'.format(field)
- else:
- field = field
-
- if isinstance(value, (str, unicode, datetime.datetime)):
- value = '"{0}"'.format(value)
- elif isinstance(value, bool):
- value = 'true' if value else 'false'
- else:
- value = value
-
- self.__string = '["{0}", {1}, {2}]'.format(
- operator,
- field,
- value)
+ if isinstance(value, datetime.datetime):
+ value = str(value)
+ self.data = [operator, field, value]
def __repr__(self):
- return str('Query: {0}'.format(self.__string))
+ return 'Query: {0}'.format(self)
def __str__(self):
- return str('{0}'.format(self.__string))
+ return json.dumps(self.json_data())
def __unicode__(self):
- return self.__string
+ return json.dumps(self.json_data())
+
+ def json_data(self):
+ return self.data
class BooleanOperator(object):
@@ -91,31 +82,28 @@
if type(query) == list:
for i in query:
self.add(i)
- elif (type(query) == str or
- isinstance(query, (BinaryOperator, InOperator,
- BooleanOperator))):
- self.operations.append(str(query))
+ elif type(query) == str:
+ self.operations.append(json.loads(query))
+ elif isinstance(query, (BinaryOperator, InOperator,
+ BooleanOperator)):
+ self.operations.append(query.json_data())
else:
raise APIError("Can only accept fixed-string queries, arrays " +
"or operator objects")
def __repr__(self):
- if len(self.operations) == 0:
- raise APIError("At least one query operation is required")
- return 'Query: ["{0}",{1}]'.format(self.operator,
- ",".join(self.operations))
+ return 'Query: {0}'.format(self)
def __str__(self):
- if len(self.operations) == 0:
- raise APIError("At least one query operation is required")
- return str('["{0}",{1}]'.format(self.operator,
- ",".join(self.operations)))
+ return json.dumps(self.json_data())
def __unicode__(self):
+ return json.dumps(self.json_data())
+
+ def json_data(self):
if len(self.operations) == 0:
raise APIError("At least one query operation is required")
- return '["{0}",{1}]'.format(self.operator,
- ",".join(self.operations))
+ return [self.operator] + self.operations
class ExtractOperator(object):
@@ -138,9 +126,9 @@
for i in field:
self.add_field(i)
elif isinstance(field, str):
- self.fields.append('"{0}"'.format(str(field)))
+ self.fields.append(field)
elif isinstance(field, FunctionOperator):
- self.fields.append(str(field))
+ self.fields.append(field.json_data())
else:
raise APIError("ExtractOperator.add_field only supports "
"lists and strings")
@@ -148,9 +136,11 @@
def add_query(self, query):
if self.query is not None:
raise APIError("Only one query is supported by ExtractOperator")
- elif isinstance(query, (str, BinaryOperator, SubqueryOperator,
+ elif isinstance(query, str):
+ self.query = json.loads(query)
+ elif isinstance(query, (BinaryOperator, SubqueryOperator,
BooleanOperator)):
- self.query = str(query)
+ self.query = query.json_data()
else:
raise APIError("ExtractOperator.add_query only supports "
"strings, BinaryOperator, BooleanOperator "
@@ -162,57 +152,37 @@
self.add_group_by(i)
elif isinstance(field, str):
if len(self.group_by) == 0:
- self.group_by.append('"group_by"')
- self.group_by.append('"{0}"'.format(str(field)))
+ self.group_by.append('group_by')
+ self.group_by.append(field)
elif isinstance(field, FunctionOperator):
if len(self.group_by) == 0:
- self.group_by.append('"group_by"')
- self.group_by.append(str(field))
+ self.group_by.append('group_by')
+ self.group_by.append(field.json_data())
else:
raise APIError("ExtractOperator.add_group_by only supports "
- "lists and strings")
+ "lists, strings, and FunctionOperator objects")
def __repr__(self):
- if len(self.fields) == 0:
- raise APIError("ExtractOperator needs at least one field")
-
- arr = ['"extract"']
- arr.append("[{0}]".format(",".join(self.fields)))
-
- if self.query is not None:
- arr.append(self.query)
- if len(self.group_by) > 0:
- arr.append("[{0}]".format(",".join(self.group_by)))
-
- return str('Query: [{0}]'.format(",".join(arr)))
+ return 'Query: {0}'.format(self)
def __str__(self):
- if len(self.fields) == 0:
- raise APIError("ExtractOperator needs at least one field")
-
- arr = ['"extract"']
- arr.append("[{0}]".format(",".join(self.fields)))
-
- if self.query is not None:
- arr.append(self.query)
- if len(self.group_by) > 0:
- arr.append("[{0}]".format(",".join(self.group_by)))
-
- return str('[{0}]'.format(",".join(arr)))
+ return json.dumps(self.json_data())
def __unicode__(self):
+ return json.dumps(self.json_data())
+
+ def json_data(self):
if len(self.fields) == 0:
raise APIError("ExtractOperator needs at least one field")
- arr = ['"extract"']
- arr.append("[{0}]".format(",".join(self.fields)))
+ arr = ['extract', self.fields]
if self.query is not None:
arr.append(self.query)
if len(self.group_by) > 0:
- arr.append("[{0}]".format(",".join(self.group_by)))
+ arr.append(self.group_by)
- return str('[{0}]'.format(",".join(arr)))
+ return arr
class FunctionOperator(object):
@@ -238,22 +208,25 @@
elif (function == 'to_string' and fmt is None):
raise APIError("Function {0} requires an extra 'fmt' parameter")
- self.arr = ['"function"', '"{0}"'.format(function)]
+ self.arr = ['function', function]
if field is not None:
- self.arr.append('"{0}"'.format(field))
+ self.arr.append(field)
if function == 'to_string':
- self.arr.append('"{0}"'.format(fmt))
+ self.arr.append(fmt)
def __repr__(self):
- return str('Query: [{0}]'.format(",".join(self.arr)))
+ return 'Query: {0}'.format(self)
def __str__(self):
- return str('[{0}]'.format(",".join(self.arr)))
+ return json.dumps(self.json_data())
def __unicode__(self):
- return str('[{0}]'.format(",".join(self.arr)))
+ return json.dumps(self.json_data())
+
+ def json_data(self):
+ return self.arr
class SubqueryOperator(object):
@@ -274,23 +247,26 @@
raise APIError("Unsupported endpoint: {0}".format(endpoint))
self.query = None
- self.arr = ['"select_{0}"'.format(endpoint)]
+ self.arr = ['select_{0}'.format(endpoint)]
def add_query(self, query):
if self.query is not None:
raise APIError("Only one query is supported by ExtractOperator")
else:
self.query = True
- self.arr.append(str(query))
+ self.arr.append(query.json_data())
def __repr__(self):
- return str('Query: [{0}]'.format(",".join(self.arr)))
+ return 'Query: {0}'.format(self)
def __str__(self):
- return str('[{0}]'.format(",".join(self.arr)))
+ return json.dumps(self.json_data())
def __unicode__(self):
- return str('[{0}]'.format(",".join(self.arr)))
+ return json.dumps(self.json_data())
+
+ def json_data(self):
+ return self.arr
class InOperator(object):
@@ -305,14 +281,17 @@
"""
def __init__(self, field):
self.query = None
- self.arr = ['"in"', '"{0}"'.format(field)]
+ self.arr = ['in', field]
def add_query(self, query):
if self.query is not None:
raise APIError("Only one query is supported by ExtractOperator")
- elif isinstance(query, (str, ExtractOperator, FromOperator)):
+ elif isinstance(query, str):
+ self.query = True
+ self.arr.append(json.loads(query))
+ elif isinstance(query, (ExtractOperator, FromOperator)):
self.query = True
- self.arr.append(str(query))
+ self.arr.append(query.json_data())
else:
raise APIError("InOperator.add_query only supports "
"strings, ExtractOperator, and"
@@ -326,8 +305,7 @@
and max(map(depth, L))+1
if (depth(values) == 1):
self.query = True
- the_arr = '["array", %s]' % values
- self.arr.append(str(the_arr).replace("'", '"'))
+ self.arr.append(['array', values])
else:
raise APIError("InOperator.add_array: cannot pass in "
"nested arrays (or empty arrays)")
@@ -337,13 +315,16 @@
"['array', [<array values>]]")
def __repr__(self):
- return str('Query: [{0}]'.format(",".join(self.arr)))
+ return 'Query: {0}'.format(self)
def __str__(self):
- return str('[{0}]'.format(",".join(self.arr)))
+ return json.dumps(self.json_data())
def __unicode__(self):
- return str('[{0}]'.format(",".join(self.arr)))
+ return json.dumps(self.json_data())
+
+ def json_data(self):
+ return self.arr
class FromOperator(object):
@@ -384,7 +365,7 @@
elif isinstance(query, (InOperator, ExtractOperator,
BinaryOperator, BooleanOperator,
FunctionOperator)):
- self.query = str(query)
+ self.query = query.json_data()
else:
raise APIError("FromOperator.add_field only supports "
"Operator Objects")
@@ -395,7 +376,7 @@
if isinstance(fields, list):
if fields_depth == 1 or fields_depth == 2:
- self.order_by = str(fields)
+ self.order_by = fields
else:
raise APIError("ExtractOperator.add_order_by only "
"supports lists of fields of depth "
@@ -418,55 +399,28 @@
raise APIError("ExtractOperator.add_offset only supports ints")
def __repr__(self):
- if self.query is None:
- raise APIError("FromOperator needs one main query")
-
- arr = ['"from"']
- arr.append('"{0}"'.format(self.endpoint))
- arr.append(self.query)
-
- if len(self.order_by) > 0:
- arr.append('["order_by", {0}]'.format(self.order_by))
- if self.limit is not None:
- arr.append('["limit", {0}]'.format(self.limit))
- if self.offset is not None:
- arr.append('["offset", {0}]'.format(self.offset))
-
- return str('Query: [{0}]'.format(",".join(arr))).replace("'", '"')
+ return 'Query: {0}'.format(self)
def __str__(self):
- if self.query is None:
- raise APIError("FromOperator needs one main query")
-
- arr = ['"from"']
- arr.append('"{0}"'.format(self.endpoint))
- arr.append(self.query)
-
- if len(self.order_by) > 0:
- arr.append('["order_by", {0}]'.format(self.order_by))
- if self.limit is not None:
- arr.append('["limit", {0}]'.format(self.limit))
- if self.offset is not None:
- arr.append('["offset", {0}]'.format(self.offset))
-
- return str('[{0}]'.format(",".join(arr))).replace("'", '"')
+ return json.dumps(self.json_data())
def __unicode__(self):
+ return json.dumps(self.json_data())
+
+ def json_data(self):
if self.query is None:
raise APIError("FromOperator needs one main query")
- arr = ['"from"']
- arr.append('"{0}"'.format(self.endpoint))
- arr.append(self.query)
+ arr = ['from', self.endpoint, self.query]
if len(self.order_by) > 0:
- arr.append('["order_by", {0}]'.format(self.order_by))
+ arr.append(['order_by', self.order_by])
if self.limit is not None:
- arr.append('["limit", {0}]'.format(self.limit))
+ arr.append(['limit', self.limit])
if self.offset is not None:
- arr.append('["offset", {0}]'.format(self.offset))
+ arr.append(['offset', self.offset])
- return str('[{0}]'.format(",".join(arr))).replace("'", '"')
+ return arr
class EqualsOperator(BinaryOperator):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pypuppetdb-1.0.0/pypuppetdb/api.py
new/pypuppetdb-1.1.0/pypuppetdb/api.py
--- old/pypuppetdb-1.0.0/pypuppetdb/api.py 2019-05-30 14:11:34.000000000
+0200
+++ new/pypuppetdb-1.1.0/pypuppetdb/api.py 2019-08-31 12:32:56.000000000
+0200
@@ -1,6 +1,7 @@
from __future__ import unicode_literals
from __future__ import absolute_import
+import hashlib
import json
import logging
import requests
@@ -47,6 +48,7 @@
'pql': 'pdb/query/v4',
'inventory': 'pdb/query/v4/inventory',
'status': 'status/v1/services/puppetdb-status',
+ 'cmd': 'pdb/cmd/v1'
}
PARAMETERS = {
@@ -58,6 +60,13 @@
'server_time': 'server_time',
}
+COMMAND_VERSION = {
+ "deactivate node": 3,
+ "replace catalog": 9,
+ "replace facts": 5,
+ "store report": 8
+}
+
ERROR_STRINGS = {
'timeout': 'Connection to PuppetDB timed out on',
'refused': 'Could not reach PuppetDB on',
@@ -385,6 +394,79 @@
self.protocol.upper()))
raise
+ def _cmd(self, command, payload):
+ """This method posts commands to PuppetDB. Provided a command and
payload
+ it will fire a request at PuppetDB. If PuppetDB can be reached and
+ answers within the timeout we'll decode the response and give it back
+ or raise for the HTTP Status Code yesPuppetDB gave back.
+
+ :param command: The PuppetDB Command we want to execute.
+ :type command: :obj:`string`
+ :param command: The payload, in wire format, specific to the command.
+ :type path: :obj:`dict`
+
+ :raises: :class:`~pypuppetdb.errors.EmptyResponseError`
+
+ :returns: The decoded response from PuppetDB
+ :rtype: :obj:`dict` or :obj:`list`
+ """
+ log.debug('_cmd called with command: {0}, data: {1}'.format(
+ command, payload))
+
+ url = self._url('cmd')
+
+ if command not in COMMAND_VERSION:
+ log.error("Only {0} supported, {1} unsupported".format(
+ list(COMMAND_VERSION.keys()), command))
+ raise APIError
+
+ params = {
+ "command": command,
+ "version": COMMAND_VERSION[command],
+ "certname": payload['certname'],
+ "checksum": hashlib.sha1(str(payload) # nosec
+ .encode('utf-8')).hexdigest()
+ }
+
+ if not self.token:
+ auth = (self.username, self.password)
+ else:
+ auth = None
+
+ try:
+ r = self._session.post(url,
+ params=params,
+ data=json.dumps(payload, default=str),
+ verify=self.ssl_verify,
+ cert=(self.ssl_cert, self.ssl_key),
+ timeout=self.timeout,
+ auth=auth)
+
+ r.raise_for_status()
+
+ json_body = r.json()
+ if json_body is not None:
+ return json_body
+ else:
+ del json_body
+ raise EmptyResponseError
+
+ except requests.exceptions.Timeout:
+ log.error("{0} {1}:{2} over {3}.".format(ERROR_STRINGS['timeout'],
+ self.host, self.port,
+ self.protocol.upper()))
+ raise
+ except requests.exceptions.ConnectionError:
+ log.error("{0} {1}:{2} over {3}.".format(ERROR_STRINGS['refused'],
+ self.host, self.port,
+ self.protocol.upper()))
+ raise
+ except requests.exceptions.HTTPError as err:
+ log.error("{0} {1}:{2} over {3}.".format(err.response.text,
+ self.host, self.port,
+ self.protocol.upper()))
+ raise
+
# Method stubs
def nodes(self, unreported=2, with_status=False, **kwargs):
@@ -863,3 +945,6 @@
:rtype: :obj:`dict`
"""
return self._query('status')
+
+ def command(self, command, payload):
+ return self._cmd(command, payload)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pypuppetdb-1.0.0/python-pypuppetdb.spec
new/pypuppetdb-1.1.0/python-pypuppetdb.spec
--- old/pypuppetdb-1.0.0/python-pypuppetdb.spec 2019-05-30 14:11:34.000000000
+0200
+++ new/pypuppetdb-1.1.0/python-pypuppetdb.spec 2019-08-31 12:32:56.000000000
+0200
@@ -1,7 +1,7 @@
%{!?python_sitelib: %global python_sitelib %(%{__python} -c "from
distutils.sysconfig import get_python_lib; print get_python_lib()")}
Name: python-pypuppetdb
-Version: 0.0.4
+Version: 1.1.0
Release: 2%{?dist}
Summary: A Python puppetdb API
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pypuppetdb-1.0.0/setup.py
new/pypuppetdb-1.1.0/setup.py
--- old/pypuppetdb-1.0.0/setup.py 2019-05-30 14:11:34.000000000 +0200
+++ new/pypuppetdb-1.1.0/setup.py 2019-08-31 12:32:56.000000000 +0200
@@ -35,6 +35,16 @@
with codecs.open('CHANGELOG.rst', encoding='utf-8') as f:
CHANGELOG = f.read()
+requirements = None
+with open('requirements.txt', 'r') as f:
+ requirements = [line.rstrip()
+ for line in f.readlines() if not line.startswith('-')]
+
+requirements_test = None
+with open('requirements-test.txt', 'r') as f:
+ requirements_test = [line.rstrip() for line in f.readlines()
+ if not line.startswith('-')]
+
setup(
name='pypuppetdb',
version=version(),
@@ -47,11 +57,9 @@
long_description='\n'.join((README, CHANGELOG)),
long_description_content_type='text/x-rst',
keywords='puppet puppetdb',
- tests_require=['tox'],
+ tests_require=requirements_test,
cmdclass={'test': Tox},
- install_requires=[
- "requests >= 2.22.0",
- ],
+ install_requires=requirements,
classifiers=[
'Development Status :: 4 - Beta',
'Intended Audience :: Developers',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pypuppetdb-1.0.0/tests/test_baseapi.py
new/pypuppetdb-1.1.0/tests/test_baseapi.py
--- old/pypuppetdb-1.0.0/tests/test_baseapi.py 2019-05-30 14:11:34.000000000
+0200
+++ new/pypuppetdb-1.1.0/tests/test_baseapi.py 2019-08-31 12:32:56.000000000
+0200
@@ -176,18 +176,22 @@
+ 'facts/macaddress/02%3A42%3Aec%3A94%3A80%3Af0'
-class TesteAPIQuery(object):
+class TestAPIQuery(object):
@mock.patch.object(requests.Session, 'request')
def test_timeout(self, get, baseapi):
get.side_effect = requests.exceptions.Timeout
with pytest.raises(requests.exceptions.Timeout):
baseapi._query('nodes')
+ with pytest.raises(requests.exceptions.Timeout):
+ baseapi._cmd('deactivate node', {'certname': ''})
@mock.patch.object(requests.Session, 'request')
def test_connectionerror(self, get, baseapi):
get.side_effect = requests.exceptions.ConnectionError
with pytest.raises(requests.exceptions.ConnectionError):
baseapi._query('nodes')
+ with pytest.raises(requests.exceptions.ConnectionError):
+ baseapi._cmd('deactivate node', {'certname': ''})
@mock.patch.object(requests.Session, 'request')
def test_httperror(self, get, baseapi):
@@ -195,6 +199,8 @@
response=requests.Response())
with pytest.raises(requests.exceptions.HTTPError):
baseapi._query('nodes')
+ with pytest.raises(requests.exceptions.HTTPError):
+ baseapi._cmd('deactivate node', {'certname': ''})
def test_setting_headers_without_token(self, baseapi):
httpretty.enable()
@@ -386,6 +392,43 @@
httpretty.disable()
httpretty.reset()
+ def test_cmd(self, baseapi, query):
+ httpretty.reset()
+ httpretty.enable()
+ stub_request('http://localhost:8080/pdb/cmd/v1',
+ method=httpretty.POST)
+ node_name = 'testnode'
+ baseapi._cmd('deactivate node', {'certname': node_name})
+ last_request = httpretty.last_request()
+ assert last_request.querystring == {
+ "certname": [node_name],
+ "command": ['deactivate node'],
+ "version": ['3'],
+ "checksum": ['b93d474970e54943aec050ee399dfb85d21e143a']
+ }
+ assert last_request.headers['Content-Type'] == 'application/json'
+ assert last_request.method == 'POST'
+ assert last_request.body == six.b(json.dumps({'certname': node_name}))
+ httpretty.disable()
+ httpretty.reset()
+
+ def test_cmd_bad_command(self, baseapi):
+ httpretty.enable()
+ stub_request('http://localhost:8080/pdb/cmd/v1')
+ with pytest.raises(pypuppetdb.errors.APIError):
+ baseapi._cmd('incorrect command', {})
+ httpretty.disable()
+ httpretty.reset()
+
+ def test_cmd_with_token_authorization(self, token_baseapi):
+ httpretty.enable()
+ stub_request('https://localhost:8080/pdb/cmd/v1',
+ method=httpretty.POST)
+ token_baseapi._cmd('deactivate node', {'certname': ''})
+ assert httpretty.last_request().path.startswith('/pdb/cmd/v1')
+ assert httpretty.last_request().headers['X-Authentication'] == \
+ 'tokenstring'
+
class TestAPIMethods(object):
def test_metric(self, baseapi):
@@ -469,3 +512,16 @@
'/status/v1/services/puppetdb-status'
httpretty.disable()
httpretty.reset()
+
+ def test_command(self, baseapi):
+ httpretty.enable()
+ stub_request(
+ 'http://localhost:8080/pdb/cmd/v1',
+ method=httpretty.POST
+ )
+ baseapi.command('deactivate node', {'certname': 'testnode'})
+ assert httpretty.last_request().path.startswith(
+ '/pdb/cmd/v1'
+ )
+ httpretty.disable()
+ httpretty.reset()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pypuppetdb-1.0.0/tests/test_querybuilder.py
new/pypuppetdb-1.1.0/tests/test_querybuilder.py
--- old/pypuppetdb-1.0.0/tests/test_querybuilder.py 2019-05-30
14:11:34.000000000 +0200
+++ new/pypuppetdb-1.1.0/tests/test_querybuilder.py 2019-08-31
12:32:56.000000000 +0200
@@ -25,9 +25,9 @@
assert str(EqualsOperator("is_virtual", True))\
== '["=", "is_virtual", true]'
assert str(EqualsOperator("bios_version", ["6.00", 5.00]))\
- == '["=", "bios_version", [\'6.00\', 5.0]]'
+ == '["=", "bios_version", ["6.00", 5.0]]'
assert str(EqualsOperator(['parameter', 'ensure'], "present"))\
- == '["=", [\'parameter\', \'ensure\'], "present"]'
+ == '["=", ["parameter", "ensure"], "present"]'
assert str(EqualsOperator(u"latest_report?", True))\
== '["=", "latest_report?", true]'
assert str(EqualsOperator("report_timestamp",
@@ -37,10 +37,10 @@
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("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]'
+ == '[">", ["parameter", "version"], 4.0]'
assert str(GreaterOperator("report_timestamp",
datetime.datetime(2016, 6, 11)))\
== '[">", "report_timestamp", "2016-06-11 00:00:00"]'
@@ -53,7 +53,7 @@
"2016-05-11T23:53:29.962Z"))\
== '["<", "producer_timestamp", "2016-05-11T23:53:29.962Z"]'
assert str(LessOperator(['parameter', 'version'], 4.0))\
- == '["<", [\'parameter\', \'version\'], 4.0]'
+ == '["<", ["parameter", "version"], 4.0]'
assert str(LessOperator("report_timestamp",
datetime.datetime(2016, 6, 11)))\
== '["<", "report_timestamp", "2016-06-11 00:00:00"]'
@@ -66,7 +66,7 @@
"2016-05-11T23:53:29.962Z"))\
== '[">=", "start_time", "2016-05-11T23:53:29.962Z"]'
assert str(GreaterEqualOperator(['parameter', 'version'], 4.0))\
- == '[">=", [\'parameter\', \'version\'], 4.0]'
+ == '[">=", ["parameter", "version"], 4.0]'
assert str(GreaterEqualOperator("report_timestamp",
datetime.datetime(2016, 6, 11)))\
== '[">=", "report_timestamp", "2016-06-11 00:00:00"]'
@@ -77,22 +77,22 @@
assert str(LessEqualOperator("end_time", "2016-05-11T23:53:29.962Z"))\
== '["<=", "end_time", "2016-05-11T23:53:29.962Z"]'
assert str(LessEqualOperator(['parameter', 'version'], 4.0))\
- == '["<=", [\'parameter\', \'version\'], 4.0]'
+ == '["<=", ["parameter", "version"], 4.0]'
assert str(LessEqualOperator("report_timestamp",
datetime.datetime(2016, 6, 11)))\
== '["<=", "report_timestamp", "2016-06-11 00:00:00"]'
def test_regex_operator(self):
assert str(RegexOperator("certname", "www\\d+\\.example\\.com"))\
- == '["~", "certname", "www\\d+\\.example\\.com"]'
+ == '["~", "certname", "www\\\\d+\\\\.example\\\\.com"]'
assert str(RegexOperator(['parameter', 'version'], "4\\.\\d+"))\
- == '["~", [\'parameter\', \'version\'], "4\\.\\d+"]'
+ == '["~", ["parameter", "version"], "4\\\\.\\\\d+"]'
def test_regex_array_operator(self):
assert str(RegexArrayOperator(
"networking",
["interfaces", "eno.*", "netmask"]))\
- == '["~>", "networking", [\'interfaces\', \'eno.*\', \'netmask\']]'
+ == '["~>", "networking", ["interfaces", "eno.*", "netmask"]]'
def test_null_operator(self):
assert str(NullOperator("expired", True))\
@@ -113,14 +113,15 @@
op.add([EqualsOperator("architecture", "x86_64"),
GreaterOperator("operatingsystemmajrelease", 6)])
- assert str(op) == '["and",["=", "operatingsystem", "CentOS"],'\
- '["=", "architecture", "x86_64"],'\
+ assert str(op) == '["and", ["=", "operatingsystem", "CentOS"], '\
+ '["=", "architecture", "x86_64"], '\
'[">", "operatingsystemmajrelease", 6]]'
- assert repr(op) == 'Query: ["and",["=", "operatingsystem", "CentOS"],'\
- '["=", "architecture", "x86_64"],'\
+ assert repr(op) == 'Query: ["and", '\
+ '["=", "operatingsystem", "CentOS"], '\
+ '["=", "architecture", "x86_64"], '\
'[">", "operatingsystemmajrelease", 6]]'
- assert unicode(op) == '["and",["=", "operatingsystem", "CentOS"],'\
- '["=", "architecture", "x86_64"],'\
+ assert unicode(op) == '["and", ["=", "operatingsystem", "CentOS"], '\
+ '["=", "architecture", "x86_64"], '\
'[">", "operatingsystemmajrelease", 6]]'
with pytest.raises(APIError):
@@ -132,14 +133,15 @@
op.add([EqualsOperator("architecture", "x86_64"),
GreaterOperator("operatingsystemmajrelease", 6)])
- assert str(op) == '["or",["=", "operatingsystem", "CentOS"],'\
- '["=", "architecture", "x86_64"],'\
+ assert str(op) == '["or", ["=", "operatingsystem", "CentOS"], '\
+ '["=", "architecture", "x86_64"], '\
'[">", "operatingsystemmajrelease", 6]]'
- assert repr(op) == 'Query: ["or",["=", "operatingsystem", "CentOS"],'\
- '["=", "architecture", "x86_64"],'\
+ assert repr(op) == 'Query: ["or", '\
+ '["=", "operatingsystem", "CentOS"], '\
+ '["=", "architecture", "x86_64"], '\
'[">", "operatingsystemmajrelease", 6]]'
- assert unicode(op) == '["or",["=", "operatingsystem", "CentOS"],'\
- '["=", "architecture", "x86_64"],'\
+ assert unicode(op) == '["or", ["=", "operatingsystem", "CentOS"], '\
+ '["=", "architecture", "x86_64"], '\
'[">", "operatingsystemmajrelease", 6]]'
with pytest.raises(APIError):
@@ -149,9 +151,9 @@
op = NotOperator()
op.add(EqualsOperator("operatingsystem", "CentOS"))
- assert str(op) == '["not",["=", "operatingsystem", "CentOS"]]'
- assert repr(op) == 'Query: ["not",["=", "operatingsystem", "CentOS"]]'
- assert unicode(op) == '["not",["=", "operatingsystem", "CentOS"]]'
+ assert str(op) == '["not", ["=", "operatingsystem", "CentOS"]]'
+ assert repr(op) == 'Query: ["not", ["=", "operatingsystem", "CentOS"]]'
+ assert unicode(op) == '["not", ["=", "operatingsystem", "CentOS"]]'
with pytest.raises(APIError):
op.add(GreaterOperator("operatingsystemmajrelease", 6))
@@ -214,12 +216,12 @@
op.add_field("certname")
op.add_field(['fact_environment', 'catalog_environment'])
- assert repr(op) == 'Query: ["extract",'\
- '["certname","fact_environment","catalog_environment"]]'
- assert str(op) == '["extract",'\
- '["certname","fact_environment","catalog_environment"]]'
- assert unicode(op) == '["extract",'\
- '["certname","fact_environment","catalog_environment"]]'
+ assert repr(op) == 'Query: ["extract", '\
+ '["certname", "fact_environment", "catalog_environment"]]'
+ assert str(op) == '["extract", '\
+ '["certname", "fact_environment", "catalog_environment"]]'
+ assert unicode(op) == '["extract", '\
+ '["certname", "fact_environment", "catalog_environment"]]'
with pytest.raises(pypuppetdb.errors.APIError):
op.add_field({'equal': 'operatingsystemrelease'})
@@ -234,14 +236,14 @@
op.add_query(EqualsOperator('domain', 'example.com'))
- assert repr(op) == 'Query: ["extract",'\
- '["certname","fact_environment","catalog_environment"],'\
+ assert repr(op) == 'Query: ["extract", '\
+ '["certname", "fact_environment", "catalog_environment"], '\
'["=", "domain", "example.com"]]'
- assert str(op) == '["extract",'\
- '["certname","fact_environment","catalog_environment"],'\
+ assert str(op) == '["extract", '\
+ '["certname", "fact_environment", "catalog_environment"], '\
'["=", "domain", "example.com"]]'
- assert unicode(op) == '["extract",'\
- '["certname","fact_environment","catalog_environment"],'\
+ assert unicode(op) == '["extract", '\
+ '["certname", "fact_environment", "catalog_environment"], '\
'["=", "domain", "example.com"]]'
with pytest.raises(pypuppetdb.errors.APIError):
@@ -257,18 +259,18 @@
with pytest.raises(pypuppetdb.errors.APIError):
op.add_group_by({"deactivated": False})
- assert repr(op) == 'Query: ["extract",'\
- '["certname","fact_environment","catalog_environment"],'\
- '["=", "domain", "example.com"],'\
- '["group_by","fact_environment","catalog_environment"]]'
- assert str(op) == '["extract",'\
- '["certname","fact_environment","catalog_environment"],'\
- '["=", "domain", "example.com"],'\
- '["group_by","fact_environment","catalog_environment"]]'
- assert unicode(op) == '["extract",'\
- '["certname","fact_environment","catalog_environment"],'\
- '["=", "domain", "example.com"],'\
- '["group_by","fact_environment","catalog_environment"]]'
+ assert repr(op) == 'Query: ["extract", '\
+ '["certname", "fact_environment", "catalog_environment"], '\
+ '["=", "domain", "example.com"], '\
+ '["group_by", "fact_environment", "catalog_environment"]]'
+ assert str(op) == '["extract", '\
+ '["certname", "fact_environment", "catalog_environment"], '\
+ '["=", "domain", "example.com"], '\
+ '["group_by", "fact_environment", "catalog_environment"]]'
+ assert unicode(op) == '["extract", '\
+ '["certname", "fact_environment", "catalog_environment"], '\
+ '["=", "domain", "example.com"], '\
+ '["group_by", "fact_environment", "catalog_environment"]]'
def test_with_add_function_operator(self):
op = ExtractOperator()
@@ -281,21 +283,21 @@
'producer_timestamp',
'FMDAY'))
- assert str(op) == '["extract",'\
- '[["function","to_string","producer_timestamp","FMDAY"],'\
- '["function","count"]],'\
- '["group_by",'\
- '["function","to_string","producer_timestamp","FMDAY"]]]'
- assert repr(op) == 'Query: ["extract",'\
- '[["function","to_string","producer_timestamp","FMDAY"],'\
- '["function","count"]],'\
- '["group_by",'\
- '["function","to_string","producer_timestamp","FMDAY"]]]'
- assert unicode(op) == '["extract",'\
- '[["function","to_string","producer_timestamp","FMDAY"],'\
- '["function","count"]],'\
- '["group_by",'\
- '["function","to_string","producer_timestamp","FMDAY"]]]'
+ assert str(op) == '["extract", '\
+ '[["function", "to_string", "producer_timestamp", "FMDAY"], '\
+ '["function", "count"]], '\
+ '["group_by", '\
+ '["function", "to_string", "producer_timestamp", "FMDAY"]]]'
+ assert repr(op) == 'Query: ["extract", '\
+ '[["function", "to_string", "producer_timestamp", "FMDAY"], '\
+ '["function", "count"]], '\
+ '["group_by", '\
+ '["function", "to_string", "producer_timestamp", "FMDAY"]]]'
+ assert unicode(op) == '["extract", '\
+ '[["function", "to_string", "producer_timestamp", "FMDAY"], '\
+ '["function", "count"]], '\
+ '["group_by", '\
+ '["function", "to_string", "producer_timestamp", "FMDAY"]]]'
class TestFunctionOperator(object):
@@ -304,58 +306,58 @@
"""
def test_count_function(self):
assert str(FunctionOperator('count')) == \
- '["function","count"]'
+ '["function", "count"]'
assert repr(FunctionOperator('count')) == \
- 'Query: ["function","count"]'
+ 'Query: ["function", "count"]'
assert unicode(FunctionOperator('count')) == \
- '["function","count"]'
+ '["function", "count"]'
assert str(FunctionOperator('count', 'domain')) == \
- '["function","count","domain"]'
+ '["function", "count", "domain"]'
assert repr(FunctionOperator('count', 'domain')) == \
- 'Query: ["function","count","domain"]'
+ 'Query: ["function", "count", "domain"]'
assert unicode(FunctionOperator('count', 'domain')) == \
- '["function","count","domain"]'
+ '["function", "count", "domain"]'
def test_avg_function(self):
assert str(FunctionOperator('avg', 'uptime')) == \
- '["function","avg","uptime"]'
+ '["function", "avg", "uptime"]'
assert repr(FunctionOperator('avg', 'uptime')) == \
- 'Query: ["function","avg","uptime"]'
+ 'Query: ["function", "avg", "uptime"]'
assert unicode(FunctionOperator('avg', 'uptime')) == \
- '["function","avg","uptime"]'
+ '["function", "avg", "uptime"]'
with pytest.raises(pypuppetdb.errors.APIError):
FunctionOperator("avg")
def test_sum_function(self):
assert str(FunctionOperator('sum', 'memoryfree_mb')) == \
- '["function","sum","memoryfree_mb"]'
+ '["function", "sum", "memoryfree_mb"]'
assert repr(FunctionOperator('sum', 'memoryfree_mb')) == \
- 'Query: ["function","sum","memoryfree_mb"]'
+ 'Query: ["function", "sum", "memoryfree_mb"]'
assert unicode(FunctionOperator('sum', 'memoryfree_mb')) == \
- '["function","sum","memoryfree_mb"]'
+ '["function", "sum", "memoryfree_mb"]'
with pytest.raises(pypuppetdb.errors.APIError):
FunctionOperator("sum")
def test_min_function(self):
assert str(FunctionOperator('min', 'kernelversion')) == \
- '["function","min","kernelversion"]'
+ '["function", "min", "kernelversion"]'
assert repr(FunctionOperator('min', 'kernelversion')) == \
- 'Query: ["function","min","kernelversion"]'
+ 'Query: ["function", "min", "kernelversion"]'
assert unicode(FunctionOperator('min', 'kernelversion')) == \
- '["function","min","kernelversion"]'
+ '["function", "min", "kernelversion"]'
with pytest.raises(pypuppetdb.errors.APIError):
FunctionOperator("min")
def test_max_function(self):
assert str(FunctionOperator('max', 'facterversion')) == \
- '["function","max","facterversion"]'
+ '["function", "max", "facterversion"]'
assert repr(FunctionOperator('max', 'facterversion')) == \
- 'Query: ["function","max","facterversion"]'
+ 'Query: ["function", "max", "facterversion"]'
assert unicode(FunctionOperator('max', 'facterversion')) == \
- '["function","max","facterversion"]'
+ '["function", "max", "facterversion"]'
with pytest.raises(pypuppetdb.errors.APIError):
FunctionOperator("max")
@@ -364,15 +366,15 @@
assert str(FunctionOperator("to_string",
'producer_timestamp',
'FMDAY')) == \
- '["function","to_string","producer_timestamp","FMDAY"]'
+ '["function", "to_string", "producer_timestamp", "FMDAY"]'
assert repr(FunctionOperator("to_string",
'producer_timestamp',
'FMDAY')) == \
- 'Query: ["function","to_string","producer_timestamp","FMDAY"]'
+ 'Query: ["function", "to_string", "producer_timestamp", "FMDAY"]'
assert unicode(FunctionOperator("to_string",
'producer_timestamp',
'FMDAY')) == \
- '["function","to_string","producer_timestamp","FMDAY"]'
+ '["function", "to_string", "producer_timestamp", "FMDAY"]'
with pytest.raises(pypuppetdb.errors.APIError):
FunctionOperator("to_string")
@@ -397,7 +399,7 @@
op = SubqueryOperator('events')
op.add_query(EqualsOperator('status', 'noop'))
- assert repr(op) == 'Query: ["select_events",'\
+ assert repr(op) == 'Query: ["select_events", '\
'["=", "status", "noop"]]'
def test_multiple_add_query(self):
@@ -417,15 +419,15 @@
"""
def test_events_endpoint(self):
assert str(InOperator('certname')) == \
- '["in","certname"]'
+ '["in", "certname"]'
op = InOperator('certname')
ex = ExtractOperator()
ex.add_field("certname")
op.add_query(ex)
- assert repr(op) == 'Query: ["in","certname",' \
- '["extract",["certname"]]]'
+ assert repr(op) == 'Query: ["in", "certname", ' \
+ '["extract", ["certname"]]]'
def test_multiple_add_query(self):
with pytest.raises(pypuppetdb.errors.APIError):
@@ -438,7 +440,7 @@
op = InOperator('certname')
op.add_array(arr)
- assert repr(op) == 'Query: ["in","certname",' \
+ assert repr(op) == 'Query: ["in", "certname", ' \
'["array", [1, "2", 3]]]'
def test_invalid_add_array(self):
@@ -476,9 +478,9 @@
fr.add_offset(10)
op.add_query(fr)
- assert repr(op) == 'Query: ["in","certname",' \
- '["from","facts",["extract",' \
- '["certname","facts"]],["offset", 10]]]'
+ assert repr(op) == 'Query: ["in", "certname", ' \
+ '["from", "facts", ["extract", ' \
+ '["certname", "facts"]], ["offset", 10]]]'
# last example on page
# https://puppet.com/docs/puppetdb/5.1/api/query/v4/ast.html
@@ -495,10 +497,10 @@
fr.add_query(ex)
op.add_query(fr)
- assert unicode(op) == '["in","certname",' \
- '["from","fact_contents",' \
- '["extract",["certname"],["and",["=", "path", ' \
- '["networking", "eth0", "macaddresses", 0]],' \
+ assert unicode(op) == '["in", "certname", ' \
+ '["from", "fact_contents", ' \
+ '["extract", ["certname"], ["and", ["=", "path", ' \
+ '["networking", "eth0", "macaddresses", 0]], ' \
'["=", "value", "aa:bb:cc:dd:ee:00"]]]]]'
@@ -521,7 +523,7 @@
op = EqualsOperator("certname", "test01")
fr.add_query(op)
- assert str(fr) == '["from","facts",["=", "certname", "test01"]]'
+ assert str(fr) == '["from", "facts", ["=", "certname", "test01"]]'
fr2 = FromOperator("facts")
op2 = "test, test, test"
@@ -537,8 +539,8 @@
fr3.add_query(op3)
assert str(fr3) == \
- '["from","facts",["extract",'\
- '["certname","fact_environment","catalog_environment"]]]'
+ '["from", "facts", ["extract", '\
+ '["certname", "fact_environment", "catalog_environment"]]]'
def test_limit_offset(self):
fr = FromOperator("facts")
@@ -547,21 +549,21 @@
fr.add_offset(10)
assert str(fr) == \
- '["from","facts",["=", "certname", "test01"],["offset", 10]]'
+ '["from", "facts", ["=", "certname", "test01"], ["offset", 10]]'
fr.add_limit(5)
assert str(fr) == \
- '["from","facts",["=", "certname",' \
- ' "test01"],["limit", 5],["offset", 10]]'
+ '["from", "facts", ["=", "certname",' \
+ ' "test01"], ["limit", 5], ["offset", 10]]'
fr.add_limit(15)
assert unicode(fr) == \
- '["from","facts",["=", "certname",' \
- ' "test01"],["limit", 15],["offset", 10]]'
+ '["from", "facts", ["=", "certname",' \
+ ' "test01"], ["limit", 15], ["offset", 10]]'
assert repr(fr) == \
- 'Query: ["from","facts",["=", "certname",' \
- ' "test01"],["limit", 15],["offset", 10]]'
+ 'Query: ["from", "facts", ["=", "certname",' \
+ ' "test01"], ["limit", 15], ["offset", 10]]'
with pytest.raises(pypuppetdb.errors.APIError):
fr.add_offset("invalid")
@@ -580,25 +582,25 @@
fr.add_order_by(o1)
assert str(fr) == \
- '["from","facts",["=", "certname", ' \
- '"test01"],["order_by", ["certname"]]]'
+ '["from", "facts", ["=", "certname", ' \
+ '"test01"], ["order_by", ["certname"]]]'
fr.add_order_by(o2)
assert repr(fr) == \
- 'Query: ["from","facts",' \
- '["=", "certname", "test01"],' \
+ 'Query: ["from", "facts", ' \
+ '["=", "certname", "test01"], ' \
'["order_by", ["certname", ' \
'["timestamp", "desc"], "facts"]]]'
assert str(fr) == \
- '["from","facts",' \
- '["=", "certname", "test01"],' \
+ '["from", "facts", ' \
+ '["=", "certname", "test01"], ' \
'["order_by", ["certname", ' \
'["timestamp", "desc"], "facts"]]]'
assert unicode(fr) == \
- '["from","facts",' \
- '["=", "certname", "test01"],' \
+ '["from", "facts", ' \
+ '["=", "certname", "test01"], ' \
'["order_by", ["certname", ' \
'["timestamp", "desc"], "facts"]]]'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pypuppetdb-1.0.0/version new/pypuppetdb-1.1.0/version
--- old/pypuppetdb-1.0.0/version 2019-05-30 14:11:34.000000000 +0200
+++ new/pypuppetdb-1.1.0/version 2019-08-31 12:32:56.000000000 +0200
@@ -1 +1 @@
-1.0.0
+1.1.0