[Pkg-puppet-devel] [python-pypuppetdb] 01/02: Imported Upstream version 0.1.1+git080614
Jonas Genannt
jonas at brachium-system.net
Wed Aug 6 17:37:27 UTC 2014
This is an automated email from the git hooks/post-receive script.
hggh-guest pushed a commit to branch master
in repository python-pypuppetdb.
commit 74f2f13fe95ba96b10639e8f6833e35e77ec34d5
Author: Jonas Genannt <jonas at brachium-system.net>
Date: Wed Aug 6 19:31:22 2014 +0200
Imported Upstream version 0.1.1+git080614
---
.coveragerc | 3 +
.gitignore | 50 ++++
.travis.yml | 13 ++
PKG-INFO | 378 -------------------------------
README.rst | 45 ++++
conftest.py | 26 +++
docs/Makefile | 153 +++++++++++++
docs/api.rst | 128 +++++++++++
docs/conf.py | 60 +++++
docs/index.rst | 37 +++
docs/make.bat | 190 ++++++++++++++++
docs/quickstart.rst | 133 +++++++++++
pypuppetdb.egg-info/PKG-INFO | 378 -------------------------------
pypuppetdb.egg-info/SOURCES.txt | 19 --
pypuppetdb.egg-info/dependency_links.txt | 1 -
pypuppetdb.egg-info/requires.txt | 1 -
pypuppetdb.egg-info/top_level.txt | 1 -
pypuppetdb/api/__init__.py | 28 ++-
pypuppetdb/api/v2.py | 6 +-
pypuppetdb/api/v3.py | 20 +-
pypuppetdb/types.py | 17 +-
python-pypuppetdb.spec | 48 ++++
setup.cfg | 10 +-
setup.py | 4 +-
test-requirements.txt | 6 +
tests/test_baseapi.py | 261 +++++++++++++++++++++
tests/test_connect.py | 17 ++
tests/test_package.py | 11 +
tests/test_types.py | 185 +++++++++++++++
tests/test_utils.py | 49 ++++
tox.ini | 11 +
31 files changed, 1475 insertions(+), 814 deletions(-)
diff --git a/.coveragerc b/.coveragerc
new file mode 100644
index 0000000..4f627e1
--- /dev/null
+++ b/.coveragerc
@@ -0,0 +1,3 @@
+[report]
+exclude_lines =
+ pragma: notest
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a845636
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,50 @@
+*.py[cod]
+
+# C extensions
+*.so
+
+# Pytest
+.cache
+__pycache__
+
+# Packages
+*.egg
+*.egg-info
+dist
+build
+eggs
+parts
+bin
+var
+sdist
+develop-eggs
+.installed.cfg
+lib
+lib64
+
+# Installer logs
+pip-log.txt
+
+# Unit test / coverage reports
+.coverage
+.tox
+nosetests.xml
+htmlcov
+
+# Translations
+*.mo
+
+# Virtualenv / pyenv
+.python-version
+.venv
+
+# Sphinx
+docs/_build
+
+# Mr Developer
+.mr.developer.cfg
+.project
+.pydevproject
+
+# OS X
+.DS_*
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..10eb870
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,13 @@
+language: python
+python:
+ - 2.6
+ - 2.7
+ - 3.3
+install:
+ - pip install -q -r test-requirements.txt --use-wheel
+ - pip install -q coverage coveralls --use-wheel
+script: coverage run --source pypuppetdb -m py.test --pep8
+after_success:
+ - coveralls
+notifications:
+ email: false
diff --git a/PKG-INFO b/PKG-INFO
deleted file mode 100644
index 4e78d5b..0000000
--- a/PKG-INFO
+++ /dev/null
@@ -1,378 +0,0 @@
-Metadata-Version: 1.1
-Name: pypuppetdb
-Version: 0.1.1
-Summary: Library for working with the PuppetDB REST API.
-Home-page: https://github.com/nedap/pypuppetdb
-Author: Daniele Sluijters
-Author-email: daniele.sluijters+pypi at gmail.com
-License: Apache License 2.0
-Description: ##########
- pypuppetdb
- ##########
-
- .. image:: https://api.travis-ci.org/nedap/pypuppetdb.png
- :target: https://travis-ci.org/nedap/pypuppetdb
-
- .. image:: https://coveralls.io/repos/nedap/pypuppetdb/badge.png
- :target: https://coeralls.io/r/nedap/pypuppetdb
-
- .. image:: https://pypip.in/d/pypuppetdb/badge.png
- :target: https://crate.io/packages/pypuppetdb
-
- .. image:: https://pypip.in/v/pypuppetdb/badge.png
- :target: https://crate.io/packages/pypuppetdb
-
- pypuppetdtb is a library to work with PuppetDB's REST API. It is implemented
- using the `requests`_ library.
-
- .. _requests: http://docs.python-requests.org/en/latest/
-
- This library is a thin wrapper around the REST API providing some convinience
- functions and objects to request and hold data from PuppetDB.
-
- To use this library you will need:
- * Python 2.6 or 2.7
- * Python 3.3
-
- Installation
- ============
-
- You can install this package from source or from PyPi.
-
- .. code-block:: bash
-
- $ pip install pypuppetdb
-
- .. code-block:: bash
-
- $ git clone https://github.com/nedap/pypuppetdb
- $ python setup.py install
-
- If you wish to hack on it clone the repository but after that run:
-
- .. code-block:: bash
-
- $ pip install -r requirements.txt
-
- This will install all the runtime requirements of pypuppetdb and the
- dependencies for the test suite and generation of documentation.
-
- Usage
- =====
-
- Once you have pypuppetdb installed you can configure it to connect to PuppetDB
- and take it from there.
-
- Connecting
- ----------
-
- The first thing you need to do is to connect with PuppetDB:
-
- .. code-block:: python
-
- >>> from pypuppetdb import connect
- >>> db = connect()
-
- Nodes
- -----
-
- The following will return a generator object yielding Node objects for every
- returned node from PuppetDB.
-
- .. code-block:: python
-
- >>> nodes = db.nodes()
- >>> for node in nodes:
- >>> print(node)
- host1
- host2
- ...
-
- To query a single node the singular `node()` can be used:
-
- .. code-block:: python
-
- >>> node = db.node('hostname')
- >>> print(node)
- hostname
-
- Node scope
- ~~~~~~~~~~
-
- The Node objects are a bit more special in that they can query for facts and
- resources themselves. Using those methods from a node object will automatically
- add a query to the request scoping the request to the node.
-
- .. code-block:: python
-
- >>> node = db.node('hostname')
- >>> print(node.fact('osfamily'))
- osfamily/hostname
-
- Facts
- -----
-
- .. code-block:: python
-
- >>> facts = db.facts('osfamily')
- >>> for fact in facts:
- >>> print(fact)
- osfamily/host1
- osfamily/host2
-
- That queries PuppetDB for the 'osfamily' fact and will yield Fact objects,
- one per node this fact is known for.
-
- Resources
- ---------
-
- .. code-block:: python
-
- >>> resources = db.resources('file')
-
- Will return a generator object containing all file resources you're managing
- across your infrastructure. This is probably a bad idea if you have a big
- number of nodes as the response will be huge.
-
- Catalogs
- ---------
-
- .. code-block:: python
-
- >>> catalog = db.catalog('hostname')
- >>> for res in catalog.get_resources():
- >>> print(res)
-
- Will return a Catalog object with the latest Catalog of the definded host. This
- catalog contains the defined Resources and Edges.
-
- Getting Help
- ============
- This project is still very new so it's not inconceivable you'll run into
- issues.
-
- For bug reports you can file an `issue`_. If you need help with something
- feel free to hit up `@daenney`_ by e-mail or find him on IRC. He can usually
- be found on `IRCnet`_ and `Freenode`_ and idles in #puppet.
-
- There's now also the #puppetboard channel on `Freenode`_ where we hang out
- and answer questions related to pypuppetdb and Puppetboard.
-
- .. _issue: https://github.com/nedap/pypuppetdb/issues
- .. _ at daenney: https://github.com/daenney
- .. _IRCnet: http://www.ircnet.org
- .. _Freenode: http://freenode.net
-
- Documentation
- =============
- API documentation is automatically generated from the docstrings using
- Sphinx's autodoc feature.
-
- Documentation will automatically be rebuilt on every push thanks to the
- Read The Docs webhook. You can `find it here`_.
-
- .. _find it here: https://pypuppetdb.readthedocs.org/en/latest/
-
- You can build the documentation manually by doing:
-
- .. code-block:: bash
-
- $ cd docs
- $ make html
-
- Doing so will only work if you have Sphinx installed, which you can acheive
- through:
-
- .. code-block:: bash
-
- $ pip install -r requirements.txt
-
- Contributing
- ============
-
- We welcome contributions to this library. However, there are a few ground
- rules contributors should be aware of.
-
- License
- -------
- This project is licensed under the Apache v2.0 License. As such, your
- contributions, once accepted, are automatically covered by this license.
-
- Commit messages
- ---------------
- Write decent commit messages. Don't use swear words and refrain from
- uninformative commit messages as 'fixed typo'.
-
- The preferred format of a commit message:
-
- ::
-
- docs/quickstart: Fixed a typo in the Nodes section.
-
- If needed, elaborate further on this commit. Feel free to write a
- complete blog post here if that helps us understand what this is
- all about.
-
- Fixes #4 and resolves #2.
-
- If you'd like a more elaborate guide on how to write and format your commit
- messages have a look at this post by `Tim Pope`_.
-
- .. _Tim Pope: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
-
- Tests
- -----
- Commits are expected to contain tests or updates to tests if they add to or
- modify the current behaviour.
-
- The test suite is powered by `pytest`_ and requires `pytest`_, `pytest-pep8`_,
- `httpretty`_ and `pytest-httpretty`_ which will be installed for you if you
- run:
-
- .. code-block:: bash
-
- $ pip install -r requirements.txt
-
- .. _pytest: http://pytest.org/latest/
- .. _pytest-pep8: https://pypi.python.org/pypi/pytest-pep8
- .. _httpretty: https://pypi.python.org/pypi/httpretty/
- .. _pytest-httpretty: https://github.com/papaeye/pytest-httpretty
-
- To run the unit tests (the ones that don't require a live PuppetDB):
-
- .. code-block:: bash
-
- $ py.test -v -m unit
-
- If the tests pass, you're golden. If not we'll have to figure out why and
- fix that. Feel free to ask for help on this.
-
- #########
- Changelog
- #########
-
- 0.1.1
- =====
-
- * Fix the license in our ``setup.py``. The license shouldn't be longer than
- 200 characters. We were including the full license tripping up tools like
- bdist_rpm.
-
- 0.1.0
- =====
- Significant changes have been made in this release. The complete v3 API is
- now supported except for query pagination.
-
- Most changes are backwards compatible except for a change in the SSL
- configuration. The previous behaviour was buggy and slightly misleading in
- the names the options took:
-
- * ``ssl`` has been renamed to ``ssl_verify`` and now defaults to ``True``.
- * Automatically use HTTPS if ``ssl_key`` and ``ssl_cert`` are provided.
-
- For additional instructions about getting SSL to work see the Quickstart
- in the documentation.
-
- Deprecation
- ------------
- Support for API v2 will be dropped in the 0.2.x release series.
-
- New features
- ------------
-
- The following features are **only** supported for **API v3**.
-
- The ``node()`` and ``nodes()`` function have gained the following options:
-
- * ``with_status=False``
- * ``unreported=2``
-
- When ``with_status`` is set to ``True`` an additional query will be made using
- the ``events-count`` endpoint scoped to the latest report. This will result in
- an additional ``events`` and ``status`` keys on the node object. ``status``
- will be either of ``changed``, ``unchanged`` or ``failed`` depending on if
- ``events`` contains ``successes`` or ``failures`` or none.
-
- By default ``unreported`` is set to ``2``. This is only in effect when
- ``with_status`` is set to ``True``. It means that if a node hasn't checked in
- for two hours it will get a ``status`` of ``unreported`` instead.
-
- New endpoints:
-
- * ``events-count``: ``events_count()``
- * ``aggregate-event-counts``: ``aggregate_event_counts()``
- * ``server-time``: ``server_time()``
- * ``version``: ``current_version()``
- * ``catalog``: ``catalog()``
-
- New types:
-
- * ``pypuppetdb.types.Catalog``
- * ``pypuppetdb.types.Edge``
-
- Changes to types:
-
- * ``pypuppetdb.types.Node`` now has:
- * ``status`` defaulting to ``None``
- * ``events`` defaulting to ``None``
- * ``unreported_time`` defaulting to ``None``
-
- 0.0.4
- =====
-
- Due to a fairly serious bug 0.0.3 was pulled from PyPi minutes after release.
-
- When a bug was fixed to be able to query for all facts we accidentally
- introduced a different bug that caused the ``facts()`` call on a node to
- query for all facts because we were resetting the query.
-
- * Fix a bug where ``node.facts()`` was causing us to query all facts because
- the query to scope our request was being reset.
-
- 0.0.3
- =====
-
- With the introduction of PuppetDB 1.5 a new API version, v3, was also
- introduced. In that same release the old ``/experimental`` endpoints
- were removed, meaning that as of PuppetDB 1.5 with the v2 API you can
- no longer get access to reports or events.
-
- In light of this the support for the experimental endpoints has been
- completely removed from pypuppetdb. As of this release you can only get
- to reports and/or events through v3 of the API.
-
- This release includes preliminary support for the v3 API. Everything that
- could be done with v2 plus the experimental endpoints is now possible on
- v3. However, more advanced funtionality has not yet been implemented. That
- will be the focus of the next release.
-
- * Removed dependency on pytz.
- * Fixed the behaviour of ``facts()`` and ``resources()``. We can now
- correctly query for all facts or resources.
- * Fixed an issue with catalog timestampless nodes.
- * Pass along the ``timeout`` option to ``connect()``.
- * Added preliminary PuppetDB API v3 support.
- * Removed support for the experimental endpoints.
- * The ``connect()`` method defaults to API v3 now.
-
- 0.0.2
- =====
- * Fix a bug in ``setup.py`` preventing successful installation.
-
- 0.0.1
- =====
- Initial release. Implements most of the v2 API.
-
-Keywords: puppet puppetdb
-Platform: UNKNOWN
-Classifier: Development Status :: 4 - Beta
-Classifier: Intended Audience :: Developers
-Classifier: Natural Language :: English
-Classifier: License :: OSI Approved :: Apache Software License
-Classifier: Operating System :: POSIX
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.6
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.3
-Classifier: Topic :: Software Development :: Libraries
diff --git a/README.rst b/README.rst
index c20d243..7d652ef 100644
--- a/README.rst
+++ b/README.rst
@@ -49,6 +49,35 @@ If you wish to hack on it clone the repository but after that run:
This will install all the runtime requirements of pypuppetdb and the
dependencies for the test suite and generation of documentation.
+Packages
+--------
+Native packages for your operating system will be provided in the near future.
+
++------------------+-----------+--------------------------------------------+
+| OS | Status | |
++==================+===========+============================================+
+| Debian 6/Squeeze | planned | Requires Backports |
++------------------+-----------+--------------------------------------------+
+| Debian 7/Wheezy | planned | |
++------------------+-----------+--------------------------------------------+
+| Ubuntu 13.04 | planned | |
++------------------+-----------+--------------------------------------------+
+| Ubuntu 13.10 | planned | |
++------------------+-----------+--------------------------------------------+
+| CentOS/RHEL 5 | n/a | Python 2.4 |
++------------------+-----------+--------------------------------------------+
+| CentOS/RHEL 6 | planned | |
++------------------+-----------+--------------------------------------------+
+| `ArchLinux`_ | available | Maintained by `Niels Abspoel`_ |
++------------------+-----------+--------------------------------------------+
+| `OpenBSD`_ | available | Maintained by `Jasper Lievisse Adriaanse`_ |
++------------------+-----------+--------------------------------------------+
+
+.. _ArchLinux: https://aur.archlinux.org/packages/python2-pypuppetdb/
+.. _Niels Abspoel: https://github.com/aboe76
+.. _Jasper Lievisse Adriaanse: https://github.com/jasperla
+.. _OpenBSD: http://www.openbsd.org/cgi-bin/cvsweb/ports/databases/py-puppetdb/
+
Usage
=====
@@ -138,6 +167,20 @@ Catalogs
Will return a Catalog object with the latest Catalog of the definded host. This
catalog contains the defined Resources and Edges.
+.. code-block:: python
+
+ >>> catalog = db.catalog('hostname')
+ >>> resource = catalog.get_resource('Service','ntp')
+ >>> for rel in resource.relationships:
+ >>> print(rel)
+ Class[Ntp] - contains - Service[ntp]
+ File[/etc/ntp.conf] - notifies - Service[ntp]
+ File[/etc/ntp.conf] - required-by - Service[ntp]
+
+
+Will return all Relationships of a given Resource defined by type and title.
+This will list all linked other Resources and the type of relationship.
+
Getting Help
============
This project is still very new so it's not inconceivable you'll run into
@@ -190,6 +233,8 @@ License
This project is licensed under the Apache v2.0 License. As such, your
contributions, once accepted, are automatically covered by this license.
+Copyright (c) 2013-2014 Daniele Sluijters
+
Commit messages
---------------
Write decent commit messages. Don't use swear words and refrain from
diff --git a/conftest.py b/conftest.py
new file mode 100644
index 0000000..d636314
--- /dev/null
+++ b/conftest.py
@@ -0,0 +1,26 @@
+import pytest
+import pypuppetdb
+
+
+# Set up our API objects
+ at pytest.fixture(scope='session')
+def api2():
+ """Set up a connection to PuppetDB with API version 2."""
+ return pypuppetdb.connect(api_version=2)
+
+
+ at pytest.fixture(scope='session')
+def api3():
+ """Set up a connection to PuppetDB with API version 3."""
+ return pypuppetdb.connect(api_version=3)
+
+
+ at pytest.fixture
+def baseapi():
+ return pypuppetdb.api.BaseAPI(3)
+
+
+ at pytest.fixture
+def utc():
+ """Create a UTC object."""
+ return pypuppetdb.utils.UTC()
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644
index 0000000..168b975
--- /dev/null
+++ b/docs/Makefile
@@ -0,0 +1,153 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " devhelp to make HTML files and a Devhelp project"
+ @echo " epub to make an epub"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " text to make text files"
+ @echo " man to make manual pages"
+ @echo " texinfo to make Texinfo files"
+ @echo " info to make Texinfo files and run them through makeinfo"
+ @echo " gettext to make PO message catalogs"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+ -rm -rf $(BUILDDIR)/*
+
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/PyPuppetDB.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/PyPuppetDB.qhc"
+
+devhelp:
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/PyPuppetDB"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/PyPuppetDB"
+ @echo "# devhelp"
+
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo
+ @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+ @echo "Run \`make' in that directory to run these through makeinfo" \
+ "(use \`make info' here to do that automatically)."
+
+info:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo "Running Texinfo files through makeinfo..."
+ make -C $(BUILDDIR)/texinfo info
+ @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+ $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+ @echo
+ @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
diff --git a/docs/api.rst b/docs/api.rst
new file mode 100644
index 0000000..d471d76
--- /dev/null
+++ b/docs/api.rst
@@ -0,0 +1,128 @@
+.. _api:
+
+Developer Interface
+===================
+
+.. module:: pypuppetdb
+
+This part of the documentation covers all the interfaces of PyPuppetDB.
+It will cover how the API is set up and how to configure which version of
+the API to use.
+
+Lazy objects
+------------
+
+.. note::
+
+ Reading in the response from PuppetDB is currently greedy, it will read in
+ the complete response no matter the size. This will change once streaming
+ and pagination support are added to PuppetDB's endpoints.
+
+In order for pypuppetdb to be able to deal with big datasets those functions
+that are expected to return more than a single item are implemented as
+generators.
+
+This is usually the case for functions with a plural name like
+:func:`~pypuppetdb.api.v2.API.nodes` or :func:`~pypuppetdb.api.v2.API.facts`.
+
+Because of this we'll only query PuppetDB once you start iterating over the
+generator object. Until that time not a single request is fired at PuppetDB.
+
+Most singular functions are implemented by calling their plural counterpart
+and then iterating over the generator, immediately exhausting the generator
+and returning a single/the first object.
+
+Main Interface
+--------------
+
+What you'll usually need to do is use the :func:`connect` method to set up a
+connection with PuppetDB and indicate which version of the API you want to
+talk.
+.. autofunction:: connect
+
+API objects
+-----------
+
+The PuppetDB API is versioned. We currently have a v1, v2 and v3.
+
+In order to work with this structure PyPuppetDB consists of a :class:`BaseAPI
+<BaseAPI>` class that factors out identical code between different versions.
+
+Every version of the API has its own class which inherits from our
+:class:`BaseAPI <BaseAPI>`.
+
+.. data:: API_VERSIONS
+
+ :obj:`dict` of :obj:`int`::obj:`string` pairs representing the API version
+ and it's URL prefix.
+
+ We currently only handle API version 2 though it should be fairly easy to
+ support version 1 should we want to.
+
+BaseAPI
+^^^^^^^
+
+.. autoclass:: pypuppetdb.api.BaseAPI
+ :members:
+ :private-members:
+
+v2.API
+^^^^^^
+.. autoclass:: pypuppetdb.api.v2.API
+ :members:
+ :inherited-members:
+ :private-members:
+ :show-inheritance:
+
+v3.API
+^^^^^^
+.. autoclass:: pypuppetdb.api.v3.API
+ :members:
+ :inherited-members:
+ :private-members:
+ :show-inheritance:
+
+Types
+-----
+
+In order to facilitate working with the API most methods like
+:meth:`~pypuppetdb.api.v2.API.nodes` don't return the decoded
+JSON response but return an object representation of the querried
+endpoints data.
+
+.. autoclass:: pypuppetdb.types.Node
+ :members:
+.. autoclass:: pypuppetdb.types.Fact
+.. autoclass:: pypuppetdb.types.Resource
+.. autoclass:: pypuppetdb.types.Event
+.. autoclass:: pypuppetdb.types.Report
+.. autoclass:: pypuppetdb.types.Catalog
+.. autoclass:: pypuppetdb.types.Edge
+
+Errors
+------
+
+Unfortunately things can go haywire. PuppetDB might not be reachable
+or complain about our query, requests might have to wait too long to
+recieve a response or the body is just too big to handle.
+
+In that case, we'll throw an exception at you.
+
+.. autoexception:: pypuppetdb.errors.APIError
+.. autoexception:: pypuppetdb.errors.ImproperlyConfiguredError
+ :show-inheritance:
+.. autoexception:: pypuppetdb.errors.UnsupportedVersionError
+ :show-inheritance:
+.. autoexception:: pypuppetdb.errors.DoesNotComputeError
+ :show-inheritance:
+.. autoexception:: pypuppetdb.errors.EmptyResponseError
+ :show-inheritance:
+
+Utilities
+---------
+
+A few functions that are used across this library have been put
+into their own :mod:`utils` module.
+
+.. autoclass:: pypuppetdb.utils.UTC
+.. autofunction:: pypuppetdb.utils.json_to_datetime
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 0000000..952db68
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,60 @@
+# -*- coding: utf-8 -*-
+import sys, os
+
+pypuppetdb_root = os.path.dirname(os.path.abspath('.'))
+sys.path.insert(0, pypuppetdb_root)
+import pypuppetdb.package
+
+# -- General configuration -----------------------------------------------------
+
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode']
+
+templates_path = ['_templates']
+
+source_suffix = '.rst'
+
+master_doc = 'index'
+
+project = pypuppetdb.package.__title__
+copyright = '{0}, {1}'.format(pypuppetdb.package.__year__,
+ pypuppetdb.package.__author__)
+
+version = pypuppetdb.package.__version__
+release = version
+
+language = 'en'
+
+exclude_patterns = ['_build']
+
+pygments_style = 'sphinx'
+
+# -- Options for HTML output ---------------------------------------------------
+
+html_theme = 'default'
+
+html_static_path = ['_static']
+
+htmlhelp_basename = 'pypuppetdbdoc'
+
+# -- Options for LaTeX output --------------------------------------------------
+
+latex_documents = [
+ ('index', 'pypuppetdb.tex', u'pypuppetdb Documentation',
+ u'Daniele Sluijters', 'manual'),
+]
+
+
+# -- Options for manual page output --------------------------------------------
+
+man_pages = [
+ ('index', 'pypuppetdb', u'pypuppetdb Documentation',
+ [u'Daniele Sluijters'], 1)
+]
+
+# -- Options for Texinfo output ------------------------------------------------
+
+texinfo_documents = [
+ ('index', 'pypuppetdb', u'pypuppetdb Documentation',
+ u'Daniele Sluijters', 'pypuppetdb', 'Library to work with the PuppetDB REST API.',
+ 'Miscellaneous'),
+]
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 0000000..3060cfa
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,37 @@
+Welcome to pypuppetdb's documentation!
+======================================
+
+.. note::
+ This is a very new project and still changing at a rapid pace. As such the
+ only documentation currently available is the API documentation and a brief
+ Getting Started guide. Once this settles down tutorials and other documentation
+ will be added over time.
+
+Getting started
+---------------
+
+The quickstart should get you up and running with pypuppetdb and familiarise
+you with how this library works.
+
+.. toctree::
+ :maxdepth: 2
+
+ quickstart
+
+API Documentation
+-----------------
+
+This part of the documentation focusses on the classes, methods and functions
+that make up this library.
+
+.. toctree::
+ :maxdepth: 2
+
+ api
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`search`
+
diff --git a/docs/make.bat b/docs/make.bat
new file mode 100644
index 0000000..fe092a2
--- /dev/null
+++ b/docs/make.bat
@@ -0,0 +1,190 @@
+ at ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+set I18NSPHINXOPTS=%SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+ set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+ set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+ :help
+ echo.Please use `make ^<target^>` where ^<target^> is one of
+ echo. html to make standalone HTML files
+ echo. dirhtml to make HTML files named index.html in directories
+ echo. singlehtml to make a single large HTML file
+ echo. pickle to make pickle files
+ echo. json to make JSON files
+ echo. htmlhelp to make HTML files and a HTML help project
+ echo. qthelp to make HTML files and a qthelp project
+ echo. devhelp to make HTML files and a Devhelp project
+ echo. epub to make an epub
+ echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+ echo. text to make text files
+ echo. man to make manual pages
+ echo. texinfo to make Texinfo files
+ echo. gettext to make PO message catalogs
+ echo. changes to make an overview over all changed/added/deprecated items
+ echo. linkcheck to check all external links for integrity
+ echo. doctest to run all doctests embedded in the documentation if enabled
+ goto end
+)
+
+if "%1" == "clean" (
+ for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+ del /q /s %BUILDDIR%\*
+ goto end
+)
+
+if "%1" == "html" (
+ %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+ goto end
+)
+
+if "%1" == "dirhtml" (
+ %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+ goto end
+)
+
+if "%1" == "singlehtml" (
+ %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+ goto end
+)
+
+if "%1" == "pickle" (
+ %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the pickle files.
+ goto end
+)
+
+if "%1" == "json" (
+ %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the JSON files.
+ goto end
+)
+
+if "%1" == "htmlhelp" (
+ %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+ goto end
+)
+
+if "%1" == "qthelp" (
+ %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+ echo.^> qcollectiongenerator %BUILDDIR%\qthelp\PyPuppetDB.qhcp
+ echo.To view the help file:
+ echo.^> assistant -collectionFile %BUILDDIR%\qthelp\PyPuppetDB.ghc
+ goto end
+)
+
+if "%1" == "devhelp" (
+ %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished.
+ goto end
+)
+
+if "%1" == "epub" (
+ %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The epub file is in %BUILDDIR%/epub.
+ goto end
+)
+
+if "%1" == "latex" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "text" (
+ %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The text files are in %BUILDDIR%/text.
+ goto end
+)
+
+if "%1" == "man" (
+ %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The manual pages are in %BUILDDIR%/man.
+ goto end
+)
+
+if "%1" == "texinfo" (
+ %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
+ goto end
+)
+
+if "%1" == "gettext" (
+ %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
+ goto end
+)
+
+if "%1" == "changes" (
+ %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.The overview file is in %BUILDDIR%/changes.
+ goto end
+)
+
+if "%1" == "linkcheck" (
+ %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+ goto end
+)
+
+if "%1" == "doctest" (
+ %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+ goto end
+)
+
+:end
diff --git a/docs/quickstart.rst b/docs/quickstart.rst
new file mode 100644
index 0000000..a38015d
--- /dev/null
+++ b/docs/quickstart.rst
@@ -0,0 +1,133 @@
+.. _quickstart:
+
+Quickstart
+==========
+Once you have pypuppetdb installed you can configure it to connect to PuppetDB
+and take it from there.
+
+Connecting
+----------
+
+The first thing you need to do is to connect with PuppetDB:
+
+.. code-block:: python
+
+ >>> from pypuppetdb import connect
+ >>> db = connect()
+
+Nodes
+-----
+
+The following will return a generator object yielding Node objects for every
+returned node from PuppetDB.
+
+.. code-block:: python
+
+ >>> nodes = db.nodes()
+ >>> for node in nodes:
+ >>> print(node)
+ host1
+ host2
+ ...
+
+To query a single node the singular `node()` can be used:
+
+.. code-block:: python
+
+ >>> node = db.node('hostname')
+ >>> print(node)
+ hostname
+
+Node scope
+~~~~~~~~~~
+
+The Node objects are a bit more special in that they can query for facts and
+resources themselves. Using those methods from a node object will automatically
+add a query to the request scoping the request to the node.
+
+.. code-block:: python
+
+ >>> node = db.node('hostname')
+ >>> print(node.fact('osfamily'))
+ osfamily/hostname
+
+Facts
+-----
+
+.. code-block:: python
+
+ >>> facts = db.facts('osfamily')
+ >>> for fact in facts:
+ >>> print(fact)
+ osfamily/host1
+ osfamily/host2
+
+That queries PuppetDB for the 'osfamily' fact and will yield Fact objects,
+one per node this fact is known for.
+
+Resources
+---------
+
+.. code-block:: python
+
+ >>> resources = db.resources('file')
+
+Will return a generator object containing all file resources you're managing
+across your infrastructure. This is probably a bad idea if you have a big
+number of nodes as the response will be huge.
+
+SSL
+---
+If PuppetDB and the tool that's using pypuppetdb aren't located on the same
+machine you will have to connect securely to PuppetDB using client certificates
+according to PuppetDB's default configuration.
+
+You can also tell PuppetDB to accept plain connections from anywhere instead
+of just the local machine but **don't do that**.
+
+Pypuppetdb can handle this easily for you. It requires two things:
+ * Generate with your Puppet CA a key pair that you want to use
+ * Tell pypuppetdb to use this keypair.
+
+Generate keypair
+~~~~~~~~~~~~~~~~
+
+On your Puppet Master or dedicated Puppet CA server:
+
+.. code-block:: console
+
+ $ puppet cert generate <service_name>
+
+Once that's done you'll need to get the public and private keyfile and copy
+them over. You can find those in Puppet's ``$ssldir``, usually
+``/var/lib/puppet/ssl``:
+
+ * private key: ``$ssldir/private_keys/<service_name>.pem``
+ * public key: ``$ssldir/ca/signed/<service_name>.pem``
+
+Configure pypuppetdb for SSL
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Once you have those you can pass them to pypuppetdb's ``connect()``:
+
+.. code-block:: python
+
+ >>> db = connect(ssl_key='/path/to/private.pem', ssl_cert='/path/to/public.pem')
+
+If both ``ssl_key`` and ``ssl_cert`` are provided pypuppetdb will automatically
+switch over to using HTTPS instead.
+
+By default pypuppetdb will also verify the certificate PuppetDB is serving.
+This means that the authority that signed PuppetDB's server certificate, most
+likely your Puppet Master, must be part of the trusted set of certificates for
+your OS or must be added to that set. Those certificates are usually found in
+``/etc/ssl/certs`` on Linux-y machines.
+
+For Debian, install your Puppet Master's certificate in
+``/usr/local/share/ca-certifiactes`` with a ``.crt`` extension and then run
+``dpkg-reconfigure ca-certificates`` as per
+``/usr/share/doc/ca-certificates/README.Debian``. This of course requires the
+``ca-certificates`` package to be installed.
+
+If you do not wish to do so or for whatever reason want to disable the
+verification of PuppetDB's certificate you can pass in ``ssl_verify=False``.
diff --git a/pypuppetdb.egg-info/PKG-INFO b/pypuppetdb.egg-info/PKG-INFO
deleted file mode 100644
index 4e78d5b..0000000
--- a/pypuppetdb.egg-info/PKG-INFO
+++ /dev/null
@@ -1,378 +0,0 @@
-Metadata-Version: 1.1
-Name: pypuppetdb
-Version: 0.1.1
-Summary: Library for working with the PuppetDB REST API.
-Home-page: https://github.com/nedap/pypuppetdb
-Author: Daniele Sluijters
-Author-email: daniele.sluijters+pypi at gmail.com
-License: Apache License 2.0
-Description: ##########
- pypuppetdb
- ##########
-
- .. image:: https://api.travis-ci.org/nedap/pypuppetdb.png
- :target: https://travis-ci.org/nedap/pypuppetdb
-
- .. image:: https://coveralls.io/repos/nedap/pypuppetdb/badge.png
- :target: https://coeralls.io/r/nedap/pypuppetdb
-
- .. image:: https://pypip.in/d/pypuppetdb/badge.png
- :target: https://crate.io/packages/pypuppetdb
-
- .. image:: https://pypip.in/v/pypuppetdb/badge.png
- :target: https://crate.io/packages/pypuppetdb
-
- pypuppetdtb is a library to work with PuppetDB's REST API. It is implemented
- using the `requests`_ library.
-
- .. _requests: http://docs.python-requests.org/en/latest/
-
- This library is a thin wrapper around the REST API providing some convinience
- functions and objects to request and hold data from PuppetDB.
-
- To use this library you will need:
- * Python 2.6 or 2.7
- * Python 3.3
-
- Installation
- ============
-
- You can install this package from source or from PyPi.
-
- .. code-block:: bash
-
- $ pip install pypuppetdb
-
- .. code-block:: bash
-
- $ git clone https://github.com/nedap/pypuppetdb
- $ python setup.py install
-
- If you wish to hack on it clone the repository but after that run:
-
- .. code-block:: bash
-
- $ pip install -r requirements.txt
-
- This will install all the runtime requirements of pypuppetdb and the
- dependencies for the test suite and generation of documentation.
-
- Usage
- =====
-
- Once you have pypuppetdb installed you can configure it to connect to PuppetDB
- and take it from there.
-
- Connecting
- ----------
-
- The first thing you need to do is to connect with PuppetDB:
-
- .. code-block:: python
-
- >>> from pypuppetdb import connect
- >>> db = connect()
-
- Nodes
- -----
-
- The following will return a generator object yielding Node objects for every
- returned node from PuppetDB.
-
- .. code-block:: python
-
- >>> nodes = db.nodes()
- >>> for node in nodes:
- >>> print(node)
- host1
- host2
- ...
-
- To query a single node the singular `node()` can be used:
-
- .. code-block:: python
-
- >>> node = db.node('hostname')
- >>> print(node)
- hostname
-
- Node scope
- ~~~~~~~~~~
-
- The Node objects are a bit more special in that they can query for facts and
- resources themselves. Using those methods from a node object will automatically
- add a query to the request scoping the request to the node.
-
- .. code-block:: python
-
- >>> node = db.node('hostname')
- >>> print(node.fact('osfamily'))
- osfamily/hostname
-
- Facts
- -----
-
- .. code-block:: python
-
- >>> facts = db.facts('osfamily')
- >>> for fact in facts:
- >>> print(fact)
- osfamily/host1
- osfamily/host2
-
- That queries PuppetDB for the 'osfamily' fact and will yield Fact objects,
- one per node this fact is known for.
-
- Resources
- ---------
-
- .. code-block:: python
-
- >>> resources = db.resources('file')
-
- Will return a generator object containing all file resources you're managing
- across your infrastructure. This is probably a bad idea if you have a big
- number of nodes as the response will be huge.
-
- Catalogs
- ---------
-
- .. code-block:: python
-
- >>> catalog = db.catalog('hostname')
- >>> for res in catalog.get_resources():
- >>> print(res)
-
- Will return a Catalog object with the latest Catalog of the definded host. This
- catalog contains the defined Resources and Edges.
-
- Getting Help
- ============
- This project is still very new so it's not inconceivable you'll run into
- issues.
-
- For bug reports you can file an `issue`_. If you need help with something
- feel free to hit up `@daenney`_ by e-mail or find him on IRC. He can usually
- be found on `IRCnet`_ and `Freenode`_ and idles in #puppet.
-
- There's now also the #puppetboard channel on `Freenode`_ where we hang out
- and answer questions related to pypuppetdb and Puppetboard.
-
- .. _issue: https://github.com/nedap/pypuppetdb/issues
- .. _ at daenney: https://github.com/daenney
- .. _IRCnet: http://www.ircnet.org
- .. _Freenode: http://freenode.net
-
- Documentation
- =============
- API documentation is automatically generated from the docstrings using
- Sphinx's autodoc feature.
-
- Documentation will automatically be rebuilt on every push thanks to the
- Read The Docs webhook. You can `find it here`_.
-
- .. _find it here: https://pypuppetdb.readthedocs.org/en/latest/
-
- You can build the documentation manually by doing:
-
- .. code-block:: bash
-
- $ cd docs
- $ make html
-
- Doing so will only work if you have Sphinx installed, which you can acheive
- through:
-
- .. code-block:: bash
-
- $ pip install -r requirements.txt
-
- Contributing
- ============
-
- We welcome contributions to this library. However, there are a few ground
- rules contributors should be aware of.
-
- License
- -------
- This project is licensed under the Apache v2.0 License. As such, your
- contributions, once accepted, are automatically covered by this license.
-
- Commit messages
- ---------------
- Write decent commit messages. Don't use swear words and refrain from
- uninformative commit messages as 'fixed typo'.
-
- The preferred format of a commit message:
-
- ::
-
- docs/quickstart: Fixed a typo in the Nodes section.
-
- If needed, elaborate further on this commit. Feel free to write a
- complete blog post here if that helps us understand what this is
- all about.
-
- Fixes #4 and resolves #2.
-
- If you'd like a more elaborate guide on how to write and format your commit
- messages have a look at this post by `Tim Pope`_.
-
- .. _Tim Pope: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
-
- Tests
- -----
- Commits are expected to contain tests or updates to tests if they add to or
- modify the current behaviour.
-
- The test suite is powered by `pytest`_ and requires `pytest`_, `pytest-pep8`_,
- `httpretty`_ and `pytest-httpretty`_ which will be installed for you if you
- run:
-
- .. code-block:: bash
-
- $ pip install -r requirements.txt
-
- .. _pytest: http://pytest.org/latest/
- .. _pytest-pep8: https://pypi.python.org/pypi/pytest-pep8
- .. _httpretty: https://pypi.python.org/pypi/httpretty/
- .. _pytest-httpretty: https://github.com/papaeye/pytest-httpretty
-
- To run the unit tests (the ones that don't require a live PuppetDB):
-
- .. code-block:: bash
-
- $ py.test -v -m unit
-
- If the tests pass, you're golden. If not we'll have to figure out why and
- fix that. Feel free to ask for help on this.
-
- #########
- Changelog
- #########
-
- 0.1.1
- =====
-
- * Fix the license in our ``setup.py``. The license shouldn't be longer than
- 200 characters. We were including the full license tripping up tools like
- bdist_rpm.
-
- 0.1.0
- =====
- Significant changes have been made in this release. The complete v3 API is
- now supported except for query pagination.
-
- Most changes are backwards compatible except for a change in the SSL
- configuration. The previous behaviour was buggy and slightly misleading in
- the names the options took:
-
- * ``ssl`` has been renamed to ``ssl_verify`` and now defaults to ``True``.
- * Automatically use HTTPS if ``ssl_key`` and ``ssl_cert`` are provided.
-
- For additional instructions about getting SSL to work see the Quickstart
- in the documentation.
-
- Deprecation
- ------------
- Support for API v2 will be dropped in the 0.2.x release series.
-
- New features
- ------------
-
- The following features are **only** supported for **API v3**.
-
- The ``node()`` and ``nodes()`` function have gained the following options:
-
- * ``with_status=False``
- * ``unreported=2``
-
- When ``with_status`` is set to ``True`` an additional query will be made using
- the ``events-count`` endpoint scoped to the latest report. This will result in
- an additional ``events`` and ``status`` keys on the node object. ``status``
- will be either of ``changed``, ``unchanged`` or ``failed`` depending on if
- ``events`` contains ``successes`` or ``failures`` or none.
-
- By default ``unreported`` is set to ``2``. This is only in effect when
- ``with_status`` is set to ``True``. It means that if a node hasn't checked in
- for two hours it will get a ``status`` of ``unreported`` instead.
-
- New endpoints:
-
- * ``events-count``: ``events_count()``
- * ``aggregate-event-counts``: ``aggregate_event_counts()``
- * ``server-time``: ``server_time()``
- * ``version``: ``current_version()``
- * ``catalog``: ``catalog()``
-
- New types:
-
- * ``pypuppetdb.types.Catalog``
- * ``pypuppetdb.types.Edge``
-
- Changes to types:
-
- * ``pypuppetdb.types.Node`` now has:
- * ``status`` defaulting to ``None``
- * ``events`` defaulting to ``None``
- * ``unreported_time`` defaulting to ``None``
-
- 0.0.4
- =====
-
- Due to a fairly serious bug 0.0.3 was pulled from PyPi minutes after release.
-
- When a bug was fixed to be able to query for all facts we accidentally
- introduced a different bug that caused the ``facts()`` call on a node to
- query for all facts because we were resetting the query.
-
- * Fix a bug where ``node.facts()`` was causing us to query all facts because
- the query to scope our request was being reset.
-
- 0.0.3
- =====
-
- With the introduction of PuppetDB 1.5 a new API version, v3, was also
- introduced. In that same release the old ``/experimental`` endpoints
- were removed, meaning that as of PuppetDB 1.5 with the v2 API you can
- no longer get access to reports or events.
-
- In light of this the support for the experimental endpoints has been
- completely removed from pypuppetdb. As of this release you can only get
- to reports and/or events through v3 of the API.
-
- This release includes preliminary support for the v3 API. Everything that
- could be done with v2 plus the experimental endpoints is now possible on
- v3. However, more advanced funtionality has not yet been implemented. That
- will be the focus of the next release.
-
- * Removed dependency on pytz.
- * Fixed the behaviour of ``facts()`` and ``resources()``. We can now
- correctly query for all facts or resources.
- * Fixed an issue with catalog timestampless nodes.
- * Pass along the ``timeout`` option to ``connect()``.
- * Added preliminary PuppetDB API v3 support.
- * Removed support for the experimental endpoints.
- * The ``connect()`` method defaults to API v3 now.
-
- 0.0.2
- =====
- * Fix a bug in ``setup.py`` preventing successful installation.
-
- 0.0.1
- =====
- Initial release. Implements most of the v2 API.
-
-Keywords: puppet puppetdb
-Platform: UNKNOWN
-Classifier: Development Status :: 4 - Beta
-Classifier: Intended Audience :: Developers
-Classifier: Natural Language :: English
-Classifier: License :: OSI Approved :: Apache Software License
-Classifier: Operating System :: POSIX
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.6
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.3
-Classifier: Topic :: Software Development :: Libraries
diff --git a/pypuppetdb.egg-info/SOURCES.txt b/pypuppetdb.egg-info/SOURCES.txt
deleted file mode 100644
index 54737cd..0000000
--- a/pypuppetdb.egg-info/SOURCES.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-CHANGELOG.rst
-LICENSE
-MANIFEST.in
-README.rst
-setup.cfg
-setup.py
-pypuppetdb/__init__.py
-pypuppetdb/errors.py
-pypuppetdb/package.py
-pypuppetdb/types.py
-pypuppetdb/utils.py
-pypuppetdb.egg-info/PKG-INFO
-pypuppetdb.egg-info/SOURCES.txt
-pypuppetdb.egg-info/dependency_links.txt
-pypuppetdb.egg-info/requires.txt
-pypuppetdb.egg-info/top_level.txt
-pypuppetdb/api/__init__.py
-pypuppetdb/api/v2.py
-pypuppetdb/api/v3.py
\ No newline at end of file
diff --git a/pypuppetdb.egg-info/dependency_links.txt b/pypuppetdb.egg-info/dependency_links.txt
deleted file mode 100644
index 8b13789..0000000
--- a/pypuppetdb.egg-info/dependency_links.txt
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/pypuppetdb.egg-info/requires.txt b/pypuppetdb.egg-info/requires.txt
deleted file mode 100644
index ce40e87..0000000
--- a/pypuppetdb.egg-info/requires.txt
+++ /dev/null
@@ -1 +0,0 @@
-requests >= 1.2.3
\ No newline at end of file
diff --git a/pypuppetdb.egg-info/top_level.txt b/pypuppetdb.egg-info/top_level.txt
deleted file mode 100644
index 88c4c96..0000000
--- a/pypuppetdb.egg-info/top_level.txt
+++ /dev/null
@@ -1 +0,0 @@
-pypuppetdb
diff --git a/pypuppetdb/api/__init__.py b/pypuppetdb/api/__init__.py
index a77178a..201069e 100644
--- a/pypuppetdb/api/__init__.py
+++ b/pypuppetdb/api/__init__.py
@@ -106,6 +106,12 @@ class BaseAPI(object):
self.ssl_cert = ssl_cert
self.timeout = timeout
self.endpoints = ENDPOINTS[api_version]
+ self._session = requests.Session()
+ self._session.headers = {
+ 'content-type': 'application/json',
+ 'accept': 'application/json',
+ 'accept-charset': 'utf-8'
+ }
if self.ssl_key is not None and self.ssl_cert is not None:
self.protocol = 'https'
@@ -145,6 +151,16 @@ class BaseAPI(object):
if self.last_total is not None:
return int(self.last_total)
+ def _normalize_resource_type(self, type_):
+ """Normalizes the type passed to the api by capitalizing each part
+ of the type. For example:
+
+ sysctl::value -> Sysctl::Value
+ user -> User
+
+ """
+ return '::'.join([s.capitalize() for s in type_.split('::')])
+
def _url(self, endpoint, path=None):
"""The complete URL we will end up querying. Depending on the
endpoint we pass in this will result in different URL's with
@@ -232,11 +248,6 @@ class BaseAPI(object):
count_filter))
url = self._url(endpoint, path=path)
- headers = {
- 'content-type': 'application/json',
- 'accept': 'application/json',
- 'accept-charset': 'utf-8'
- }
payload = {}
if query is not None:
@@ -260,10 +271,9 @@ class BaseAPI(object):
payload = None
try:
- r = requests.get(url, params=payload, headers=headers,
- verify=self.ssl_verify, cert=(self.ssl_cert,
- self.ssl_key),
- timeout=self.timeout)
+ r = self._session.get(url, params=payload, verify=self.ssl_verify,
+ cert=(self.ssl_cert, self.ssl_key),
+ timeout=self.timeout)
r.raise_for_status()
# get total number of results if requested with include-total
diff --git a/pypuppetdb/api/v2.py b/pypuppetdb/api/v2.py
index 185c23a..2d415d7 100644
--- a/pypuppetdb/api/v2.py
+++ b/pypuppetdb/api/v2.py
@@ -93,10 +93,8 @@ class API(BaseAPI):
This will yield a Resources object for every returned resource."""
if type_ is not None:
- # Need to capitalize the resource type since PuppetDB doesn't
- # answer to lower case type names.
- # bugs.puppetlabs.com/some_value
- type_ = type_.capitalize()
+ type_ = self._normalize_resource_type(type_)
+
if title is not None:
path = '{0}/{1}'.format(type_, title)
elif title is None:
diff --git a/pypuppetdb/api/v3.py b/pypuppetdb/api/v3.py
index f5a8705..090cae4 100644
--- a/pypuppetdb/api/v3.py
+++ b/pypuppetdb/api/v3.py
@@ -78,6 +78,8 @@ class API(BaseAPI):
node['events'] = status = status[0]
if status['successes'] > 0:
node['status'] = 'changed'
+ if status['noops'] > 0:
+ node['status'] = 'noop'
if status['failures'] > 0:
node['status'] = 'failed'
else:
@@ -150,22 +152,19 @@ class API(BaseAPI):
"""Query for resources limited by either type and/or title or query.
This will yield a Resources object for every returned resource."""
- log.debug('YOLO')
+ path = None
+
if type_ is not None:
- # Need to capitalize the resource type since PuppetDB doesn't
- # answer to lower case type names.
- # bugs.puppetlabs.com/some_value
- type_ = type_.capitalize()
+ type_ = self._normalize_resource_type(type_)
+
if title is not None:
path = '{0}/{1}'.format(type_, title)
elif title is None:
path = type_
- else:
+ elif query is None:
log.debug('Going to query for all resources. This is usually a '
'bad idea as it might return enormous amounts of '
'resources.')
- query = ''
- path = None
resources = self._query('resources', path=path, query=query)
for resource in resources:
@@ -200,12 +199,13 @@ class API(BaseAPI):
report['transaction-uuid']
)
- def events(self, query):
+ def events(self, query, order_by=None, limit=None):
"""A report is made up of events. This allows to query for events
based on the reprt hash.
This yields an Event object for every returned event."""
- events = self._query('events', query=query)
+ events = self._query('events', query=query,
+ order_by=order_by, limit=limit)
for event in events:
yield Event(
event['certname'],
diff --git a/pypuppetdb/types.py b/pypuppetdb/types.py
index 1a1af94..ad96e34 100644
--- a/pypuppetdb/types.py
+++ b/pypuppetdb/types.py
@@ -168,6 +168,8 @@ class Resource(object):
:ivar sourcefile: The Puppet manifest this resource is declared in.
:ivar sourceline: The line this resource is declared at.
:ivar parameters: :obj:`dict` with key:value pairs of parameters.
+ :ivar relationships: :obj:`list` Contains all relationships to other\
+ resources
"""
def __init__(self, node, name, type_, tags, exported, sourcefile,
sourceline, parameters={}):
@@ -179,6 +181,7 @@ class Resource(object):
self.sourcefile = sourcefile
self.sourceline = sourceline
self.parameters = parameters
+ self.relationships = []
self.__string = '{0}[{1}]'.format(self.type_, self.name)
def __repr__(self):
@@ -353,9 +356,12 @@ class Catalog(object):
'[' + edge['source']['title'] + ']'
identifier_target = edge['target']['type'] + \
'[' + edge['target']['title'] + ']'
- self.edges.append(Edge(self.resources[identifier_source],
- self.resources[identifier_target],
- edge['relationship']))
+ e = Edge(self.resources[identifier_source],
+ self.resources[identifier_target],
+ edge['relationship'])
+ self.edges.append(e)
+ self.resources[identifier_source].relationships.append(e)
+ self.resources[identifier_target].relationships.append(e)
self.__string = '{0}/{1}'.format(self.node, self.transaction_uuid)
@@ -371,6 +377,11 @@ class Catalog(object):
def get_resources(self):
return self.resources.itervalues()
+ def get_resource(self, resource_type, resource_title):
+ identifier = resource_type + \
+ '[' + resource_title + ']'
+ return self.resources[identifier]
+
def get_edges(self):
return iter(self.edges)
diff --git a/python-pypuppetdb.spec b/python-pypuppetdb.spec
new file mode 100644
index 0000000..eeda8ea
--- /dev/null
+++ b/python-pypuppetdb.spec
@@ -0,0 +1,48 @@
+%{!?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
+Release: 2%{?dist}
+Summary: A Python puppetdb API
+
+Group: Development/Languages
+License: Apache
+URL: https://github.com/nedap/pypuppetdb
+Source0: http://pypi.python.org/packages/source/p/pypuppetdb/pypuppetdb-%{version}.tar.gz
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}
+
+BuildArch: noarch
+BuildRequires: python-setuptools
+Requires: python-requests >= 1.1.0
+Requires: python >= 2.6
+
+%description
+pypuppetdb is a library to work with PuppetDB's REST API. It is implemented using the requests library.
+This library is a thin wrapper around the REST API providing some convinience functions and objects to request and hold data from PuppetDB.
+To use this library you will need: Python 2.6 or 2.7 or Python 3.3.
+
+%prep
+%setup -q -n pypuppetdb-%{version}
+%{__rm} -rf *.egg-info
+%{__sed} -i 's,^#!.*env python.*$,#!/usr/bin/python,' setup.py
+
+%build
+
+%install
+rm -rf %{buildroot}
+%{__python} setup.py install -O1 --root %{buildroot}
+
+%clean
+rm -rf %{buildroot}
+
+%files
+%defattr(-,root,root,-)
+%doc
+%{python_sitelib}/*
+
+%changelog
+* Tue Oct 15 2013 Klavs Klavsen <Klavs at EnableIT.dk> - 0.0.4-2
+- Add requirements, description and other small cleanups.
+* Mon Oct 14 2013 Klavs Klavsen <Klavs at EnableIT.dk> - 0.0.4-1
+- Initial release.
+
diff --git a/setup.cfg b/setup.cfg
index 3cfb4d5..9581b3a 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -2,14 +2,8 @@
norecursedirs = docs .tox
minversion = 2.3
markers =
- unit: mark test as a unit test. Runs without PuppetDB.
- integration: mark test as an integration test. Needs a live PuppetDB with testdata loaded.
+ unit: mark test as a unit test. Runs without PuppetDB.
+ integration: mark test as an integration test. Needs a live PuppetDB with testdata loaded.
[wheel]
universal = 1
-
-[egg_info]
-tag_build =
-tag_date = 0
-tag_svn_revision = 0
-
diff --git a/setup.py b/setup.py
index 6f5df4b..e923a9f 100644
--- a/setup.py
+++ b/setup.py
@@ -19,7 +19,7 @@ class Tox(TestCommand):
self.test_suite = True
def run_tests(self):
- #import here, cause outside the eggs aren't loaded
+ # import here, cause outside the eggs aren't loaded
import tox
errno = tox.cmdline(self.test_args)
sys.exit(errno)
@@ -32,7 +32,7 @@ with codecs.open('CHANGELOG.rst', encoding='utf-8') as f:
setup(
name='pypuppetdb',
- version='0.1.1',
+ version='0.1.1+git080614',
author='Daniele Sluijters',
author_email='daniele.sluijters+pypi at gmail.com',
packages=find_packages(),
diff --git a/test-requirements.txt b/test-requirements.txt
new file mode 100644
index 0000000..2c5db30
--- /dev/null
+++ b/test-requirements.txt
@@ -0,0 +1,6 @@
+requests==2.1.0
+pytest==2.5.0
+mock==1.0.1
+git+https://github.com/gabrielfalcao/HTTPretty.git@python-3.3-support#egg=httpretty
+pytest-pep8==1.0.5
+coverage==3.7
diff --git a/tests/test_baseapi.py b/tests/test_baseapi.py
new file mode 100644
index 0000000..cabb6f0
--- /dev/null
+++ b/tests/test_baseapi.py
@@ -0,0 +1,261 @@
+import json
+import mock
+import httpretty
+import pytest
+import requests
+import pypuppetdb
+
+
+def stub_request(url, data=None, **kwargs):
+ if data is None:
+ body = '[]'
+ else:
+ with open(data, 'r') as d:
+ body = json.load(d.read())
+ return httpretty.register_uri(httpretty.GET, url, body=body, status=200,
+ **kwargs)
+
+
+class TestBaseAPIVersion(object):
+ def test_init_v2_defaults(self):
+ v2 = pypuppetdb.api.BaseAPI(2)
+ assert v2.api_version == 'v2'
+
+ def test_init_v3_defaults(self):
+ v3 = pypuppetdb.api.BaseAPI(3)
+ assert v3.api_version == 'v3'
+
+ def test_init_invalid_version(self):
+ with pytest.raises(pypuppetdb.errors.UnsupportedVersionError):
+ vderp = pypuppetdb.api.BaseAPI(10000)
+
+
+class TestBaseAPIInitOptions(object):
+ def test_defaults(self, baseapi):
+ assert baseapi.host == 'localhost'
+ assert baseapi.port == 8080
+ assert baseapi.ssl_verify is True
+ assert baseapi.ssl_key is None
+ assert baseapi.ssl_cert is None
+ assert baseapi.timeout == 10
+ assert baseapi.protocol == 'http'
+
+ def test_host(self):
+ api = pypuppetdb.api.BaseAPI(3, host='127.0.0.1')
+ assert api.host == '127.0.0.1'
+
+ def test_port(self):
+ api = pypuppetdb.api.BaseAPI(3, port=8081)
+ assert api.port == 8081
+
+ def test_ssl_verify(self):
+ api = pypuppetdb.api.BaseAPI(3, ssl_verify=False)
+ assert api.ssl_verify is False
+ assert api.protocol == 'http'
+
+ def test_ssl_key(self):
+ api = pypuppetdb.api.BaseAPI(3, ssl_key='/a/b/c.pem')
+ assert api.ssl_key == '/a/b/c.pem'
+ assert api.protocol == 'http'
+
+ def test_ssl_cert(self):
+ api = pypuppetdb.api.BaseAPI(3, ssl_cert='/d/e/f.pem')
+ assert api.ssl_cert == '/d/e/f.pem'
+ assert api.protocol == 'http'
+
+ def test_ssl_key_and_cert(self):
+ api = pypuppetdb.api.BaseAPI(3, ssl_cert='/d/e/f.pem',
+ ssl_key='/a/b/c.pem')
+ assert api.ssl_key == '/a/b/c.pem'
+ assert api.ssl_cert == '/d/e/f.pem'
+ assert api.protocol == 'https'
+
+ def test_timeout(self):
+ api = pypuppetdb.api.BaseAPI(3, timeout=20)
+ assert api.timeout == 20
+
+
+class TestBaseAPIProperties(object):
+ def test_version(self, baseapi):
+ assert baseapi.version == 'v3'
+
+ def test_base_url(self, baseapi):
+ assert baseapi.base_url == 'http://localhost:8080'
+
+ def test_base_url_ssl(self, baseapi):
+ baseapi.protocol = 'https' # slightly evil
+ assert baseapi.base_url == 'https://localhost:8080'
+
+ def test_total(self, baseapi):
+ baseapi.last_total = 10 # slightly evil
+ assert baseapi.total == 10
+
+
+class TestBaseAPIURL(object):
+ def test_without_path(self, baseapi):
+ assert baseapi._url('nodes') == 'http://localhost:8080/v3/nodes'
+
+ def test_with_invalid_endpoint(self, baseapi):
+ with pytest.raises(pypuppetdb.errors.APIError):
+ baseapi._url('this_will-Never+Ex1s7')
+
+ def test_with_path(self, baseapi):
+ url = baseapi._url('nodes', path='node1.example.com')
+ assert url == 'http://localhost:8080/v3/nodes/node1.example.com'
+
+
+class TesteAPIQuery(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')
+
+ @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')
+
+ @mock.patch.object(requests.Session, 'request')
+ def test_httperror(self, get, baseapi):
+ get.side_effect = requests.exceptions.HTTPError(
+ response=requests.Response())
+ with pytest.raises(requests.exceptions.HTTPError):
+ baseapi._query('nodes')
+
+ def test_setting_headers(self, baseapi):
+ httpretty.enable()
+ stub_request('http://localhost:8080/v3/nodes')
+ baseapi._query('nodes') # need to query some endpoint
+ request_headers = dict(httpretty.last_request().headers)
+ assert request_headers['Accept'] == 'application/json'
+ assert request_headers['Content-Type'] == 'application/json'
+ assert request_headers['Accept-Charset'] == 'utf-8'
+ assert request_headers['Host'] == 'localhost:8080'
+ assert httpretty.last_request().path == '/v3/nodes'
+ httpretty.disable()
+ httpretty.reset()
+
+ def test_with_path(self, baseapi):
+ httpretty.enable()
+ stub_request('http://localhost:8080/v3/nodes/node1')
+ baseapi._query('nodes', path='node1')
+ assert httpretty.last_request().path == '/v3/nodes/node1'
+ httpretty.disable()
+ httpretty.reset()
+
+ def test_with_query(self, baseapi):
+ httpretty.enable()
+ stub_request('http://localhost:8080/v3/nodes')
+ baseapi._query('nodes', query='["certname", "=", "node1"]')
+ assert httpretty.last_request().querystring == {
+ 'query': ['["certname", "=", "node1"]']}
+ httpretty.disable()
+ httpretty.reset()
+
+ def test_with_order(self, baseapi):
+ httpretty.enable()
+ stub_request('http://localhost:8080/v3/nodes')
+ baseapi._query('nodes', order_by='ted')
+ assert httpretty.last_request().querystring == {
+ 'order-by': ['ted']}
+ httpretty.disable()
+ httpretty.reset()
+
+ def test_with_limit(self, baseapi):
+ httpretty.enable()
+ stub_request('http://localhost:8080/v3/nodes')
+ baseapi._query('nodes', limit=1)
+ assert httpretty.last_request().querystring == {
+ 'limit': ['1']}
+ httpretty.disable()
+ httpretty.reset()
+
+ def test_with_include_total(self, baseapi):
+ httpretty.enable()
+ stub_request('http://localhost:8080/v3/nodes')
+ baseapi._query('nodes', include_total=True)
+ assert httpretty.last_request().querystring == {
+ 'include-total': ['true']}
+ httpretty.disable()
+ httpretty.reset()
+
+ def test_with_offset(self, baseapi):
+ httpretty.enable()
+ stub_request('http://localhost:8080/v3/nodes')
+ baseapi._query('nodes', offset=1)
+ assert httpretty.last_request().querystring == {
+ 'offset': ['1']}
+ httpretty.disable()
+ httpretty.reset()
+
+ def test_with_summarize_by(self, baseapi):
+ httpretty.enable()
+ stub_request('http://localhost:8080/v3/nodes')
+ baseapi._query('nodes', summarize_by=1)
+ assert httpretty.last_request().querystring == {
+ 'summarize-by': ['1']}
+ httpretty.disable()
+ httpretty.reset()
+
+ def test_with_count_by(self, baseapi):
+ httpretty.enable()
+ stub_request('http://localhost:8080/v3/nodes')
+ baseapi._query('nodes', count_by=1)
+ assert httpretty.last_request().querystring == {
+ 'count-by': ['1']}
+ httpretty.disable()
+ httpretty.reset()
+
+ def test_with_count_filter(self, baseapi):
+ httpretty.enable()
+ stub_request('http://localhost:8080/v3/nodes')
+ baseapi._query('nodes', count_filter=1)
+ assert httpretty.last_request().querystring == {
+ 'count-filter': ['1']}
+ httpretty.disable()
+ httpretty.reset()
+
+ def test_response_empty(self, baseapi):
+ httpretty.enable()
+ httpretty.register_uri(httpretty.GET, 'http://localhost:8080/v3/nodes',
+ body=json.dumps(None))
+ with pytest.raises(pypuppetdb.errors.EmptyResponseError):
+ baseapi._query('nodes')
+
+ def test_response_x_records(self, baseapi):
+ httpretty.enable()
+ httpretty.register_uri(httpretty.GET, 'http://localhost:8080/v3/nodes',
+ adding_headers={
+ 'X-Records': 256},
+ body='[]',
+ )
+ baseapi._query('nodes', include_total=True)
+ assert baseapi.total == 256
+
+
+class TestAPIMethods(object):
+ def test_nodes(self, baseapi):
+ with pytest.raises(NotImplementedError):
+ baseapi.nodes()
+
+ def test_node(self, baseapi):
+ with pytest.raises(NotImplementedError):
+ baseapi.node()
+
+ def test_facts(self, baseapi):
+ with pytest.raises(NotImplementedError):
+ baseapi.facts()
+
+ def test_resources(self, baseapi):
+ with pytest.raises(NotImplementedError):
+ baseapi.resources()
+
+ def test_metric(self, baseapi):
+ httpretty.enable()
+ stub_request('http://localhost:8080/v3/metrics/mbean/test')
+ baseapi.metric('test')
+ assert httpretty.last_request().path == '/v3/metrics/mbean/test'
+ httpretty.disable()
+ httpretty.reset()
diff --git a/tests/test_connect.py b/tests/test_connect.py
new file mode 100644
index 0000000..5beb2a5
--- /dev/null
+++ b/tests/test_connect.py
@@ -0,0 +1,17 @@
+import pytest
+import pypuppetdb
+
+
+def test_connect_unknown_api_version():
+ with pytest.raises(pypuppetdb.errors.UnsupportedVersionError):
+ pypuppetdb.connect(api_version=1)
+
+
+def test_connect_api_v2():
+ puppetdb = pypuppetdb.connect(api_version=2)
+ assert puppetdb.version == 'v2'
+
+
+def test_connect_api_v3():
+ puppetdb = pypuppetdb.connect(api_version=3)
+ assert puppetdb.version == 'v3'
diff --git a/tests/test_package.py b/tests/test_package.py
new file mode 100644
index 0000000..f492176
--- /dev/null
+++ b/tests/test_package.py
@@ -0,0 +1,11 @@
+from pypuppetdb.package import (
+ __title__, __author__, __license__,
+ __year__, __copyright__)
+
+
+def test_package():
+ assert __title__ == 'pypuppetdb'
+ assert __author__ == 'Daniele Sluijters'
+ assert __license__ == 'Apache License 2.0'
+ assert __year__ == '2013, 2014'
+ assert __copyright__ == 'Copyright {0} {1}'.format(__year__, __author__)
diff --git a/tests/test_types.py b/tests/test_types.py
new file mode 100644
index 0000000..ed01630
--- /dev/null
+++ b/tests/test_types.py
@@ -0,0 +1,185 @@
+import sys
+
+from pypuppetdb.utils import json_to_datetime
+from pypuppetdb.types import (
+ Node, Fact, Resource,
+ Report, Event, Catalog, Edge
+ )
+
+if sys.version_info >= (3, 0):
+ unicode = str
+
+
+class TestNode(object):
+ """Test the Node object."""
+ 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 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.report_timestamp is not None
+ assert node.facts_timestamp is not None
+ assert node.catalog_timestamp is not None
+ 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>')
+
+
+class TestFact(object):
+ """Test the Fact object."""
+ def test_fact(self):
+ fact = Fact('node', 'osfamily', 'Debian')
+
+ assert fact.node == 'node'
+ assert fact.name == 'osfamily'
+ assert fact.value == 'Debian'
+ assert str(fact) == str('osfamily/node')
+ assert unicode(fact) == unicode('osfamily/node')
+ assert repr(fact) == str('Fact: osfamily/node')
+
+
+class TestResource(object):
+ "Test the Resource object."""
+
+ def test_resource(self):
+ resource = Resource('node', '/etc/ssh/sshd_config', 'file',
+ ['class', 'ssh'], False, '/ssh/manifests/init.pp',
+ 15, parameters={
+ 'ensure': 'present',
+ 'owner': 'root',
+ 'group': 'root',
+ 'mode': '0600',
+ })
+
+ assert resource.node == 'node'
+ assert resource.name == '/etc/ssh/sshd_config'
+ assert resource.type_ == 'file'
+ assert resource.tags == ['class', 'ssh']
+ assert resource.exported is False
+ assert resource.sourcefile == '/ssh/manifests/init.pp'
+ assert resource.sourceline == 15
+ assert resource.parameters['ensure'] == 'present'
+ assert resource.parameters['owner'] == 'root'
+ assert resource.parameters['group'] == 'root'
+ assert resource.parameters['mode'] == '0600'
+ assert str(resource) == str('file[/etc/ssh/sshd_config]')
+ assert unicode(resource) == unicode('file[/etc/ssh/sshd_config]')
+ assert repr(resource) == str(
+ '<Resource: file[/etc/ssh/sshd_config]>')
+
+
+class TestReport(object):
+ """Test the Report object."""
+ def test_report(self):
+ report = Report('node1.puppet.board', 'hash#',
+ '2013-08-01T09:57:00.000Z',
+ '2013-08-01T10:57:00.000Z',
+ '2013-08-01T10:58:00.000Z',
+ '1351535883', 3, '3.2.1',
+ 'af9f16e3-75f6-4f90-acc6-f83d6524a6f3')
+
+ assert report.node == 'node1.puppet.board'
+ assert report.hash_ == 'hash#'
+ assert report.start == json_to_datetime('2013-08-01T09:57:00.000Z')
+ assert report.end == json_to_datetime('2013-08-01T10:57:00.000Z')
+ assert report.received == json_to_datetime('2013-08-01T10:58:00.000Z')
+ assert report.version == '1351535883'
+ assert report.format_ == 3
+ assert report.agent_version == '3.2.1'
+ assert report.run_time == report.end - report.start
+ assert report.transaction == 'af9f16e3-75f6-4f90-acc6-f83d6524a6f3'
+ assert str(report) == str('hash#')
+ assert unicode(report) == unicode('hash#')
+ assert repr(report) == str('Report: hash#')
+
+
+class TestEvent(object):
+ """Test the Event object."""
+ def test_event(self):
+ event = Event('node', 'failure', '2013-08-01T10:57:00.000Z',
+ 'hash#', '/etc/ssh/sshd_config', 'ensure',
+ 'Nothing to say', 'present', 'absent', 'file')
+
+ assert event.node == 'node'
+ assert event.status == 'failure'
+ assert event.failed is True
+ assert event.timestamp == json_to_datetime('2013-08-01T10:57:00.000Z')
+ assert event.hash_ == 'hash#'
+ assert event.item['title'] == '/etc/ssh/sshd_config'
+ assert event.item['type'] == 'file'
+ assert event.item['property'] == 'ensure'
+ assert event.item['message'] == 'Nothing to say'
+ assert event.item['old'] == 'absent'
+ assert event.item['new'] == 'present'
+ assert str(event) == str('file[/etc/ssh/sshd_config]/hash#')
+ assert unicode(event) == unicode('file[/etc/ssh/sshd_config]/hash#')
+ assert repr(event) == str('Event: file[/etc/ssh/sshd_config]/hash#')
+
+ def test_event_failed(self):
+ event = Event('node', 'success', '2013-08-01T10:57:00.000Z',
+ 'hash#', '/etc/ssh/sshd_config', 'ensure',
+ 'Nothing to say', 'present', 'absent', 'file')
+
+ assert event.status == 'success'
+ assert event.failed is False
+
+
+class TestCatalog(object):
+ """Test the Catalog object."""
+ def test_catalog(self):
+ catalog = Catalog('node', [], [], 'unique', None)
+ assert catalog.node == 'node'
+ assert catalog.version == 'unique'
+ assert catalog.transaction_uuid is None
+ assert catalog.resources == {}
+ assert catalog.edges == []
+ assert str(catalog) == str('node/None')
+ assert unicode(catalog) == unicode('node/None')
+ assert repr(catalog) == str(
+ '<Catalog: node/None>')
+
+
+class TestEdge(object):
+ """Test the Edge object."""
+ def test_edge(self):
+ resource_a = Resource('node', '/etc/ssh/sshd_config', 'file',
+ ['class', 'ssh'], False,
+ '/ssh/manifests/init.pp', 15, parameters={})
+
+ resource_b = Resource('node', 'sshd', 'service',
+ ['class', 'ssh'], False,
+ '/ssh/manifests/init.pp', 30, parameters={})
+
+ edge = Edge(resource_a, resource_b, 'notify')
+
+ assert edge.source == resource_a
+ assert edge.target == resource_b
+ assert edge.relationship == 'notify'
+ assert str(edge) == str(
+ 'file[/etc/ssh/sshd_config] - notify - service[sshd]')
+ assert unicode(edge) == unicode(
+ 'file[/etc/ssh/sshd_config] - notify - service[sshd]')
+ assert repr(edge) == str(
+ '<Edge: file[/etc/ssh/sshd_config] - notify - service[sshd]>')
diff --git a/tests/test_utils.py b/tests/test_utils.py
new file mode 100644
index 0000000..72498df
--- /dev/null
+++ b/tests/test_utils.py
@@ -0,0 +1,49 @@
+from __future__ import unicode_literals
+
+import sys
+
+import pytest
+import pypuppetdb
+import datetime
+
+if sys.version_info >= (3, 0):
+ unicode = str
+
+
+class TestUTC(object):
+ """Test the UTC class."""
+
+ def test_utc_offset(self, utc):
+ assert datetime.timedelta(0) == utc.utcoffset(300)
+
+ def test_tzname(self, utc):
+ assert str('UTC') == utc.tzname(300)
+
+ def test_dst(self, utc):
+ assert datetime.timedelta(0) == utc.dst(300)
+
+ def test_magic_str(self, utc):
+ assert str('UTC') == str(utc)
+
+ def test_magic_unicode(self, utc):
+ assert 'UTC' == unicode(utc)
+
+ def test_magic_repr(self, utc):
+ assert str('<UTC>') == repr(utc)
+
+
+class TestJSONToDateTime(object):
+ """Test the json_to_datetime function."""
+
+ def test_json_to_datetime(self):
+ json_datetime = '2013-08-01T09:57:00.000Z'
+ python_datetime = pypuppetdb.utils.json_to_datetime(json_datetime)
+ assert python_datetime.dst() == datetime.timedelta(0)
+ assert python_datetime.date() == datetime.date(2013, 8, 1)
+ assert python_datetime.tzname() == 'UTC'
+ assert python_datetime.utcoffset() == datetime.timedelta(0)
+ assert python_datetime.dst() == datetime.timedelta(0)
+
+ def test_json_to_datetime_invalid(self):
+ with pytest.raises(ValueError):
+ pypuppetdb.utils.json_to_datetime('2013-08-0109:57:00.000Z')
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..3bcd69c
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,11 @@
+[tox]
+envlist = py26, py27, py33, pypy, pep8
+
+[testenv]
+commands = py.test -m 'unit'
+deps =
+ -r{toxinidir}/requirements.txt
+
+[testenv:pep8]
+basepython = python2.6
+commands = py.test --pep8 -m 'not (unit or integration)'
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-puppet/python-pypuppetdb.git
More information about the Pkg-puppet-devel
mailing list