Welcome to Mimic’s documentation!¶
Mimic is an API-compatible mock service for Openstack Compute and Rackspace’s implementation of Identity and Cloud Load Balancers. It is backed by in-memory data structure rather than a potentially expensive database.
Mimic helps with:
- fast set-up
- instant response
- cost efficient
- enables offline development
- enables ability to test unusual behaviors/errors of an api
- acts as a central repository for mocked responses from services
Documentation¶
Development¶
mimic
welcomes contributions!
File bugs and feature requests on our issue tracker on GitHub.
Getting started¶
Working on mimic
requires the installation of a small number of development
dependencies, which are listed in requirements/development.txt
. They can
be installed in a virtualenv using pip. This also installs mimic
in
editable
mode.
For example:
$ # Create a virtualenv and activate it
$ pip install --requirement requirements/development.txt
You are now ready to run the tests and build the documentation.
Some of the tox jobs may require certain packages to be installed, so having homebrew installed would be useful if developing on Mac OS.
Running tests¶
mimic
unit tests are found in the mimic/test/
directory. Then can be
run via the built-in tox
commands after setting up tox
.
$ tox -e py27
You can also run the tests for other python interpreters. We use tox, which creates a virtualenv per tox job to run tests, linting, etc.:
$ tox
...
py26: commands succeeded
py27: commands succeeded
pypy: commands succeeded
docs: commands succeeded
lint: commands succeeded
Building documentation¶
mimic
documentation is stored in the docs/
directory. It is
written in reStructured Text and rendered using Sphinx.
To build the documentation, use tox
:
$ tox -e docs
The HTML documentation index can now be found at
docs/_build/html/index.html
.
Alternately, you can use sphinx
directly, if you would like to specify
options:
$ sphinx-build -W -b html -d _tmp/doctrees docs docs/_build/html
Building a Mac application¶
The officially supported method of building of the application depends on the system python, and the pyobjc, and py2app libraries. Travis-CI is configured to build the mac application and run its tests.
To build the application and run its tests locally use the following commands.
$ cd /dir/where/mimic/lives/
$ ./build-app.sh
Once built, mimic.app
can be found in the ./dist
directory.
This application can be treated like any other mac application and moved into
~/Applications
.
To start mimic
, use the open command with the path to mimic.app
, e.g. open ./dist/mimic.app
.
When the application is running, the letter M
will be visible in the
menubar. To quit the application, simply click on the M
and select
Quit
. You can view the application logs by opening
Applications/Utilities/Console.app
.
To run mimic.app
‘s tests use
$ /path/to/mimic.app/Contents/MacOS/run-tests
The application can also built as a standalone application that does not depend on the system python. This is not the officially supported method of building the application and is not tested by Travis-CI.
To build a standalone application, py2app
requires the installation of a
non-system framework python.
In my experience, it is easiest to install a brewed 2.7 python.
To install a brew python, you’ll need to have homebrew installed.
The following commands will build the standalone application and run its tests.
$ brew install python
$ cd /dir/where/mimic/lives/
$ # build a virtualenv using the brewed python
$ virtualenv -p /usr/local/bin/python2.7 ./venv
$ source ./venv/bin/activate
$ # install mimic's dependencies including pyobjc and py2app
$ pip install -r requirements/production.txt
$ pip install -r requirements/mac-app.txt
$ python setup.py py2app
$ ./dist/mimic.app/Contents/MacOS/run-tests
Submitting patches¶
- If you have access to the mimic repository, always make a new branch for your work.
- If you don’t have access to the mimic repository, working on branches in your fork is also nice because that will you can work on more than one PR at a time.
- Patches should be small to facilitate easier review.
Code¶
When in doubt, refer to PEP 8 for Python code (with some exceptions).
You can check if your code meets our automated requirements by running
flake8
against it. Even better would be to run the tox
job:
$ tox -e lint
...
lint: commands succeeded
congratulations :)
Write comments as complete sentences.
Every Python code file must contain:
from __future__ import absolute_import, division
Tests¶
All code changes must be accompanied by unit tests with 100% code coverage (as measured by the tool coverage.)
To test code coverage you’ll need to install detox and coverage. They can be installed by running:
pip install --user requirements/toolchain.txt
(Or you may prefer to install those requirements in a virtualenv
.)
Then run:
$ coverage erase \
&& detox \
&& coverage combine \
&& coverage html
And open htmlcov/index.html
in your web browser.
Documentation¶
All features should be documented with prose in the docs
section.
To ensure it builds and passes style checks you can run doc8 against it or
run our tox
job to lint docs. We also provide a spell-check job for docs:
$ tox -e docs
docs: commands succeeded
congratulations :)
$ tox -e docs-spellcheck
docs-spellcheck: commands succeeded
congratulations :)
$ tox -e docs-linkcheck
docs-linkcheck: commands succeeded
congratulations :)
The spell-check can catch jargon or abbreviations - if you are sure it is not
an error, please add that word to the spelling_wordlist.txt
in
alphabetical order.
Docstrings¶
Docstrings generally follow pep257, with a few exceptions. They should be written like this:
def some_function(some_arg):
"""
Does some things.
:param some_arg: Some argument.
"""
So, specifically:
- Always use three double quotes.
- Put the three double quotes on their own line.
- No blank line at the end.
- Use Sphinx parameter/attribute documentation syntax.
The same job that lints code also lints docstrings:
$ tox -e lint
...
lint: commands succeeded
congratulations :)
Documentation Documentation¶
Here are some things we’re going to document and how we’re going to document them.
There should be a document describing how to write your own API mock plugin.
- reference the Twisted documentation for writing plugins as a prerequisite
- provide an example of the file that goes into mimic/plugins,
dummy_plugin.py is a good start but it fails to explain what a real
resource might look like that responds to API requests
- unlike dummy_plugin.py, the IAPIMock implementer class ought to live in an application module, the plugin should only contain the instantiation.
- better naming might help explain why you have to make separate “API mock” and “Region” objects.
- explain what a twisted web resource is, reference twisted docs for the interface and klein docs for how to produce your own resource with nice route decorators
- implement catalog_entries
- are you implementing a crazy endpoint that manipulates the tenant ID?
manipulate it here.
- remember tenant ID may be None, because the core needs to allocate URI
prefixes before there are any tenants. maybe this really ought to be a
different API; the difference in meaning is that
catalog_entries(None)
must enumerate all regions that any user might possibly ever be able to access, whereascatalog_entries(not_none)
can return different regions for different tenants if it wants to (for example, simulating limited availability).- this is super confusing, and technically unnecessary; it just made the implementation slightly easier to do in the first place. really all the URI prefixes could be allocated on demand as individual tenants receive particular services/region pairs for the first time, obviating the need for this weird implementation detail. possibly file an issue for this and just fix it before writing the final docs so we don’t have to explain.
- remember tenant ID may be None, because the core needs to allocate URI
prefixes before there are any tenants. maybe this really ought to be a
different API; the difference in meaning is that
- return entries. canonical region right now is “ORD” but hopefully we can eventually change this API at some point to support a suggested list of regions from some configuration, pass in that list and then honor it here.
- are you implementing a crazy endpoint that manipulates the tenant ID?
manipulate it here.
- implement resource_for_region
- this gets called on every request
- guideline: use klein to build your hierarchy since that makes it easier
- note that you can always use whatever twisted.web resources make sense, if you want to toss a static hierarchy in there you don’t need to use klein, just make a static.File or a static.Data (perhaps note this at the end?)
- to-do implementation-wise: we really ought to have a JSON serializer as a
decorator or something so everybody doesn’t have to actually type
“
dumps
” all the time - note where the “region” is in the hierarchy; there will be some URI prefix
which you hopefully don’t care about (passed in as the
resource_for_region
argument) but you have to handle all segments from the end of the thing that Mimic has allocated for you: including your “prefix”; so if your “prefix” to the Endpoint construction incatalog_entries
is “v5” then your routes need to all begin “/v5/<string:tenant_id>/”. The object returned from _that_ route is actually the specific tenant’s service endpoint. - implementation note: t.w.resource lifecycle management is weird, and a bit hard to explain. It would be nice to tell the developer at this point that they can store some kind of state on the session or associated with the tenant, but given that each resource is implicitly created with each request, it’s a bit tricky to do that. perhaps we should expose the “session” object we’re already keeping around in MimicCore to application code, or a dictionary associated with it, so that we can easily have per-tenant state.
Change Logs¶
Next Version¶
- The Cinder V2 API now has limited support for the List volumes with details endpoint.