@@ -4,7 +4,6 @@ eventlet.monkey_patch(socket=True, select=True)
|
||||
import json
|
||||
import requests
|
||||
|
||||
from barbicanclient.common import config
|
||||
from barbicanclient.secrets import Secret
|
||||
from barbicanclient.orders import Order
|
||||
from barbicanclient.common import auth
|
||||
@@ -15,9 +14,8 @@ from openstack.common.timeutils import parse_isotime
|
||||
from urlparse import urljoin
|
||||
|
||||
|
||||
config.parse_args()
|
||||
log.setup('barbicanclient')
|
||||
LOG = log.getLogger(__name__)
|
||||
log.setup('barbicanclient')
|
||||
|
||||
|
||||
class Connection(object):
|
||||
@@ -80,7 +78,6 @@ class Connection(object):
|
||||
self._session.verify = True
|
||||
|
||||
if token:
|
||||
LOG.warn(_("Bypassing authentication - using provided token"))
|
||||
self.auth_token = token
|
||||
else:
|
||||
LOG.debug(_("Authenticating token"))
|
||||
@@ -105,22 +102,43 @@ class Connection(object):
|
||||
self._token = value
|
||||
self._session.headers['X-Auth-Token'] = value
|
||||
|
||||
def list_secrets(self):
|
||||
def list_secrets(self, limit=10, offset=0):
|
||||
"""
|
||||
Returns the list of secrets for the auth'd tenant
|
||||
Returns a tuple containing three items: a list of secrets pertaining
|
||||
to the given offset and limit, a reference to the previous set of
|
||||
secrets, and a reference to the next set of secrets. Either of the
|
||||
references may be None.
|
||||
"""
|
||||
LOG.debug(_("Listing secrets"))
|
||||
href = "{0}/{1}?limit=100".format(self._tenant, self.SECRETS_PATH)
|
||||
LOG.debug(_("Listing secrets - offset: {0}, limit: {1}").format(offset,
|
||||
limit))
|
||||
href = "{0}/{1}?limit={2}&offset={3}".format(self._tenant,
|
||||
self.SECRETS_PATH,
|
||||
limit, offset)
|
||||
return self.list_secrets_by_href(href)
|
||||
|
||||
def list_secrets_by_href(self, href):
|
||||
"""
|
||||
Returns a tuple containing three items: a list of secrets pertaining
|
||||
to the offset and limit within href, a reference to the previous set
|
||||
of secrets, and a reference to the next set of secrets. Either of the
|
||||
references may be None.
|
||||
"""
|
||||
LOG.debug(_("Listing secrets by href"))
|
||||
LOG.debug("href: {0}".format(href))
|
||||
if href is None:
|
||||
return [], None, None
|
||||
|
||||
hdrs, body = self._perform_http(href=href, method='GET')
|
||||
LOG.debug(_("Response - headers: {0}\nbody: {1}").format(hdrs, body))
|
||||
|
||||
secrets_dict = body['secrets']
|
||||
secrets = []
|
||||
for s in secrets_dict:
|
||||
secrets.append(Secret(self._conn, s))
|
||||
secrets = [Secret(self._conn, s) for s in secrets_dict]
|
||||
|
||||
return secrets
|
||||
prev_ref = body.get('previous')
|
||||
|
||||
next_ref = body.get('next')
|
||||
|
||||
return secrets, prev_ref, next_ref
|
||||
|
||||
def create_secret(self,
|
||||
mime_type,
|
||||
@@ -130,6 +148,18 @@ class Connection(object):
|
||||
bit_length=None,
|
||||
cypher_type=None,
|
||||
expiration=None):
|
||||
"""
|
||||
Creates and returns a Secret object with all of its metadata filled in.
|
||||
|
||||
arguments:
|
||||
mime_type - The MIME type of the secret
|
||||
plain_text - The unencrypted secret
|
||||
name - A friendly name for the secret
|
||||
algorithm - The algorithm the secret is used with
|
||||
bit_length - The bit length of the secret
|
||||
cypher_type - The cypher type (e.g. block cipher mode of operation)
|
||||
expiration - The expiration time for the secret in ISO 8601 format
|
||||
"""
|
||||
LOG.debug(_("Creating secret of mime_type {0}").format(mime_type))
|
||||
href = "{0}/{1}".format(self._tenant, self.SECRETS_PATH)
|
||||
LOG.debug(_("href: {0}").format(href))
|
||||
@@ -154,52 +184,91 @@ class Connection(object):
|
||||
return self.get_secret(body['secret_ref'])
|
||||
|
||||
def delete_secret_by_id(self, secret_id):
|
||||
"""
|
||||
Deletes a secret using its UUID
|
||||
"""
|
||||
href = "{0}/{1}/{2}".format(self._tenant, self.SECRETS_PATH, secret_id)
|
||||
LOG.info(_("Deleting secret - Secret ID: {0}").format(secret_id))
|
||||
return self.delete_secret(href)
|
||||
|
||||
def delete_secret(self, href):
|
||||
"""
|
||||
Deletes a secret using its full reference
|
||||
"""
|
||||
hdrs, body = self._perform_http(href=href, method='DELETE')
|
||||
LOG.debug(_("Response - headers: {0}\nbody: {1}").format(hdrs, body))
|
||||
|
||||
def get_secret_by_id(self, secret_id):
|
||||
"""
|
||||
Returns a Secret object using the secret's UUID
|
||||
"""
|
||||
LOG.debug(_("Getting secret - Secret ID: {0}").format(secret_id))
|
||||
href = "{0}/{1}/{2}".format(self._tenant, self.SECRETS_PATH, secret_id)
|
||||
return self.get_secret(href)
|
||||
|
||||
def get_secret(self, href):
|
||||
"""
|
||||
Returns a Secret object using the secret's full reference
|
||||
"""
|
||||
hdrs, body = self._perform_http(href=href, method='GET')
|
||||
LOG.debug(_("Response - headers: {0}\nbody: {1}").format(hdrs, body))
|
||||
return Secret(self._conn, body)
|
||||
|
||||
def get_raw_secret_by_id(self, secret_id, mime_type):
|
||||
"""
|
||||
Returns the raw secret using the secret's UUID and MIME type
|
||||
"""
|
||||
LOG.debug(_("Getting raw secret - Secret ID: {0}").format(secret_id))
|
||||
href = "{0}/{1}/{2}".format(self._tenant, self.SECRETS_PATH, secret_id)
|
||||
return self.get_raw_secret(href, mime_type)
|
||||
|
||||
def get_raw_secret(self, href, mime_type):
|
||||
"""
|
||||
Returns the raw secret using the secret's UUID and MIME type
|
||||
"""
|
||||
hdrs = {"Accept": mime_type}
|
||||
hdrs, body = self._perform_http(href=href, method='GET', headers=hdrs,
|
||||
parse_json=False)
|
||||
LOG.debug(_("Response - headers: {0}\nbody: {1}").format(hdrs, body))
|
||||
return body
|
||||
|
||||
def list_orders(self):
|
||||
def list_orders(self, limit=10, offset=0):
|
||||
"""
|
||||
Returns the list of orders
|
||||
Returns a tuple containing three items: a list of orders pertaining
|
||||
to the given offset and limit, a reference to the previous set of
|
||||
orders, and a reference to the next set of orders. Either of the
|
||||
references may be None.
|
||||
"""
|
||||
LOG.debug(_("Listing orders"))
|
||||
href = "{0}/{1}?limit=100".format(self._tenant, self.ORDERS_PATH)
|
||||
LOG.debug(_("Listing orders - offset: {0}, limit: {1}").format(offset,
|
||||
limit))
|
||||
href = "{0}/{1}?limit={2}&offset={3}".format(self._tenant,
|
||||
self.ORDERS_PATH,
|
||||
limit, offset)
|
||||
return self.list_orders_by_href(href)
|
||||
|
||||
def list_orders_by_href(self, href):
|
||||
"""
|
||||
Returns a tuple containing three items: a list of orders pertaining
|
||||
to the offset and limit within href, a reference to the previous set
|
||||
of orders, and a reference to the next set of orders. Either of the
|
||||
references may be None.
|
||||
"""
|
||||
LOG.debug(_("Listing orders by href"))
|
||||
LOG.debug("href: {0}".format(href))
|
||||
if href is None:
|
||||
return [], None, None
|
||||
|
||||
hdrs, body = self._perform_http(href=href, method='GET')
|
||||
LOG.debug(_("Response - headers: {0}\nbody: {1}").format(hdrs, body))
|
||||
|
||||
orders_dict = body['orders']
|
||||
orders = []
|
||||
for o in orders_dict:
|
||||
orders.append(Order(self._conn, o))
|
||||
orders = [Order(self._conn, o) for o in orders_dict]
|
||||
|
||||
return orders
|
||||
prev_ref = body.get('previous')
|
||||
|
||||
next_ref = body.get('next')
|
||||
|
||||
return orders, prev_ref, next_ref
|
||||
|
||||
def create_order(self,
|
||||
mime_type,
|
||||
@@ -207,6 +276,16 @@ class Connection(object):
|
||||
algorithm=None,
|
||||
bit_length=None,
|
||||
cypher_type=None):
|
||||
"""
|
||||
Creates and returns an Order object with all of its metadata filled in.
|
||||
|
||||
arguments:
|
||||
mime_type - The MIME type of the secret
|
||||
name - A friendly name for the secret
|
||||
algorithm - The algorithm the secret is used with
|
||||
bit_length - The bit length of the secret
|
||||
cypher_type - The cypher type (e.g. block cipher mode of operation)
|
||||
"""
|
||||
LOG.debug(_("Creating order of mime_type {0}").format(mime_type))
|
||||
href = "{0}/{1}".format(self._tenant, self.ORDERS_PATH)
|
||||
LOG.debug("href: {0}".format(href))
|
||||
@@ -227,20 +306,32 @@ class Connection(object):
|
||||
return self.get_order(body['order_ref'])
|
||||
|
||||
def delete_order_by_id(self, order_id):
|
||||
"""
|
||||
Deletes an order using its UUID
|
||||
"""
|
||||
LOG.info(_("Deleting order - Order ID: {0}").format(order_id))
|
||||
href = "{0}/{1}/{2}".format(self._tenant, self.ORDERS_PATH, order_id)
|
||||
return self.delete_order(href)
|
||||
|
||||
def delete_order(self, href):
|
||||
"""
|
||||
Deletes an order using its full reference
|
||||
"""
|
||||
hdrs, body = self._perform_http(href=href, method='DELETE')
|
||||
LOG.debug(_("Response - headers: {0}\nbody: {1}").format(hdrs, body))
|
||||
|
||||
def get_order_by_id(self, order_id):
|
||||
"""
|
||||
Returns an Order object using the order's UUID
|
||||
"""
|
||||
LOG.debug(_("Getting order - Order ID: {0}").format(order_id))
|
||||
href = "{0}/{1}/{2}".format(self._tenant, self.ORDERS_PATH, order_id)
|
||||
return self.get_order(href)
|
||||
|
||||
def get_order(self, href):
|
||||
"""
|
||||
Returns an Order object using the order's full reference
|
||||
"""
|
||||
hdrs, body = self._perform_http(href=href, method='GET')
|
||||
LOG.debug(_("Response - headers: {0}\nbody: {1}").format(hdrs, body))
|
||||
return Order(self._conn, body)
|
||||
|
||||
@@ -36,4 +36,11 @@ class Order(object):
|
||||
self.connection.delete_order(self)
|
||||
|
||||
def __str__(self):
|
||||
return "<Order %s>" % self.id
|
||||
return ("Order - ID: {0}\n"
|
||||
" order reference: {1}\n"
|
||||
" secret reference: {2}\n"
|
||||
" created: {3}\n"
|
||||
" status: {4}\n"
|
||||
.format(self.id, self.order_ref, self.secret_ref, self.created,
|
||||
self.status)
|
||||
)
|
||||
|
||||
@@ -39,4 +39,16 @@ class Secret(object):
|
||||
return self._id
|
||||
|
||||
def __str__(self):
|
||||
return "<Secret %s>" % self.id
|
||||
return ("Secret - ID: {0}\n"
|
||||
" reference: {1}\n"
|
||||
" name: {2}\n"
|
||||
" created: {3}\n"
|
||||
" MIME type: {4}\n"
|
||||
" status: {5}\n"
|
||||
" bit length: {6}\n"
|
||||
" algorithm: {7}\n"
|
||||
" cypher type: {8}\n"
|
||||
.format(self.id, self.secret_ref, self.name, self.created,
|
||||
self.mime_type, self.status, self.bit_length,
|
||||
self.algorithm, self.cypher_type)
|
||||
)
|
||||
|
||||
185
keep
Executable file
185
keep
Executable file
@@ -0,0 +1,185 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import argparse
|
||||
import os
|
||||
|
||||
from barbicanclient import client
|
||||
|
||||
|
||||
class Keep:
|
||||
def __init__(self):
|
||||
self.parser = self.get_main_parser()
|
||||
self.subparsers = self.parser.add_subparsers(title='subcommands',
|
||||
description=
|
||||
'Action to perform')
|
||||
self.add_create_args()
|
||||
self.add_delete_args()
|
||||
self.add_get_args()
|
||||
self.add_list_args()
|
||||
|
||||
def get_main_parser(self):
|
||||
parser = argparse.ArgumentParser(description='Access the Barbican'
|
||||
' key management sevice.')
|
||||
parser.add_argument('type',
|
||||
choices=["order", "secret"],
|
||||
help="type to operate on")
|
||||
parser.add_argument('--auth_endpoint', '-A',
|
||||
default=env('OS_AUTH_URL'),
|
||||
help='the URL to authenticate against (default: '
|
||||
'%(default)s)')
|
||||
parser.add_argument('--user', '-U', default=env('OS_USERNAME'),
|
||||
help='the user to authenticate as (default: %(de'
|
||||
'fault)s)')
|
||||
parser.add_argument('--password', '-P', default=env('OS_PASSWORD'),
|
||||
help='the API key or password to authenticate with'
|
||||
' (default: %(default)s)')
|
||||
parser.add_argument('--tenant', '-T', default=env('OS_TENANT_NAME'),
|
||||
help='the tenant ID (default: %(default)s)')
|
||||
parser.add_argument('--endpoint', '-E', default=env('SERVICE_ENDPOINT')
|
||||
, help='the URL of the barbican server (default: %'
|
||||
'(default)s)')
|
||||
parser.add_argument('--token', '-K', default=env('SERVICE_TOKEN'),
|
||||
help='the authentication token (default: %(default'
|
||||
')s)')
|
||||
return parser
|
||||
|
||||
def add_create_args(self):
|
||||
create_parser = self.subparsers.add_parser('create', help='Create a '
|
||||
'secret or an order')
|
||||
create_parser.add_argument('--mime_type', '-m', default='text/plain',
|
||||
help='the MIME type of the raw secret (defa'
|
||||
'ult: %(default)s)')
|
||||
create_parser.add_argument('--name', '-n', help='a human-friendly name'
|
||||
' used only for reference')
|
||||
create_parser.add_argument('--algorithm', '-a', help='the algorithm us'
|
||||
'ed only for reference')
|
||||
create_parser.add_argument('--bit_length', '-b', default=256,
|
||||
help='the bit length of the secret used '
|
||||
'only for reference (default: %(default)s)',
|
||||
type=int)
|
||||
create_parser.add_argument('--cypher_type', '-c', help='the cypher typ'
|
||||
'e used only for reference')
|
||||
create_parser.add_argument('--plain_text', '-p', help='the unencrypted'
|
||||
' secret (only used for secrets)')
|
||||
create_parser.add_argument('--expiration', '-e', help='the expiration '
|
||||
'time for the secret in ISO 8601 format '
|
||||
'(only used for secrets)')
|
||||
create_parser.set_defaults(func=self.create)
|
||||
|
||||
def add_delete_args(self):
|
||||
delete_parser = self.subparsers.add_parser('delete', help='Delete a se'
|
||||
'cret or an order by provid'
|
||||
'ing its UUID')
|
||||
delete_parser.add_argument('UUID', help='the universally unique identi'
|
||||
'fier of the the secret or order')
|
||||
delete_parser.set_defaults(func=self.delete)
|
||||
|
||||
def add_get_args(self):
|
||||
get_parser = self.subparsers.add_parser('get', help='Retrieve a secret'
|
||||
' or an order by providing its'
|
||||
' UUID.')
|
||||
get_parser.add_argument('UUID', help='the universally unique identi'
|
||||
'fier of the the secret or order')
|
||||
get_parser.add_argument('--raw', '-r', help='if specified, gets the ra'
|
||||
'w secret of type specified with --mime_type ('
|
||||
'only used for secrets)', action='store_true')
|
||||
get_parser.add_argument('--mime_type', '-m', default='text/plain',
|
||||
help='the MIME type of the raw secret (defa'
|
||||
'ult: %(default)s; only used for secrets)')
|
||||
get_parser.set_defaults(func=self.get)
|
||||
|
||||
def add_list_args(self):
|
||||
list_parser = self.subparsers.add_parser('list',
|
||||
help='List secrets or orders')
|
||||
list_parser.add_argument('--limit', '-l', default=10, help='specify t'
|
||||
'he limit to the number of items to list per'
|
||||
' page (default: %(default)s; maximum: 100)',
|
||||
type=int)
|
||||
list_parser.add_argument('--offset', '-o', default=0, help='specify t'
|
||||
'he page offset (default: %(default)s)',
|
||||
type=int)
|
||||
list_parser.add_argument('--URI', '-u', help='the full reference to '
|
||||
'what is to be listed; put in quotes to avoid'
|
||||
' backgrounding when \'&\' is in the URI')
|
||||
list_parser.set_defaults(func=self.lst)
|
||||
|
||||
def create(self, args):
|
||||
if args.type == 'secret':
|
||||
secret = self.conn.create_secret(args.mime_type,
|
||||
args.plain_text,
|
||||
args.name,
|
||||
args.algorithm,
|
||||
args.bit_length,
|
||||
args.cypher_type,
|
||||
args.expiration)
|
||||
print secret
|
||||
else:
|
||||
order = self.conn.create_order(args.mime_type,
|
||||
args.name,
|
||||
args.algorithm,
|
||||
args.bit_length,
|
||||
args.cypher_type)
|
||||
print order
|
||||
|
||||
def delete(self, args):
|
||||
if args.type == 'secret':
|
||||
self.conn.delete_secret_by_id(args.UUID)
|
||||
else:
|
||||
self.conn.delete_order_by_id(args.UUID)
|
||||
|
||||
def get(self, args):
|
||||
if args.type == 'secret':
|
||||
if args.raw:
|
||||
print self.conn.get_raw_secret_by_id(args.UUID, args.mime_type)
|
||||
else:
|
||||
print self.conn.get_secret_by_id(args.UUID)
|
||||
else:
|
||||
print self.conn.get_order_by_id(args.UUID)
|
||||
|
||||
def lst(self, args):
|
||||
if args.type == 'secret':
|
||||
if args.URI:
|
||||
l = self.conn.list_secrets_by_href(args.URI)
|
||||
else:
|
||||
l = self.conn.list_secrets(args.limit, args.offset)
|
||||
else:
|
||||
if args.URI:
|
||||
l = self.conn.list_orders_by_href(args.URI)
|
||||
else:
|
||||
l = self.conn.list_orders(args.limit, args.offset)
|
||||
for i in l[0]:
|
||||
print i
|
||||
print 'Displayed {0} {1}s - offset: {2}'.format(len(l[0]), args.type,
|
||||
args.offset)
|
||||
|
||||
def execute(self):
|
||||
args = self.parser.parse_args()
|
||||
self.conn = client.Connection(args.auth_endpoint, args.user,
|
||||
args.password, args.tenant,
|
||||
args.token,
|
||||
endpoint=args.endpoint)
|
||||
args.func(args)
|
||||
|
||||
|
||||
def env(*vars, **kwargs):
|
||||
"""Search for the first defined of possibly many env vars
|
||||
|
||||
Returns the first environment variable defined in vars, or
|
||||
returns the default defined in kwargs.
|
||||
|
||||
Source: Keystone's shell.py
|
||||
"""
|
||||
for v in vars:
|
||||
value = os.environ.get(v, None)
|
||||
if value:
|
||||
return value
|
||||
return kwargs.get('default', '')
|
||||
|
||||
|
||||
def main():
|
||||
k = Keep()
|
||||
k.execute()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
3
setup.py
3
setup.py
@@ -54,5 +54,6 @@ setuptools.setup(
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Environment :: No Input/Output (Daemon)',
|
||||
]
|
||||
],
|
||||
scripts = ['keep']
|
||||
)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
# limitations under the License.
|
||||
|
||||
import json
|
||||
import unittest
|
||||
import unittest2 as unittest
|
||||
|
||||
from mock import MagicMock
|
||||
|
||||
@@ -146,10 +146,13 @@ class WhenTestingConnection(unittest.TestCase):
|
||||
body0 = {'secrets': []}
|
||||
secrets = []
|
||||
self.request.return_value.content = json.dumps(body0)
|
||||
self.assertTrue(self._are_equivalent(secrets,
|
||||
self.connection.list_secrets()))
|
||||
secret_list, prev_ref, next_ref = self.connection.list_secrets(0, 0)
|
||||
self.assertTrue(self._are_equivalent(secrets, secret_list))
|
||||
self.assertIsNone(prev_ref)
|
||||
self.assertIsNone(next_ref)
|
||||
|
||||
def test_list_single_secret(self):
|
||||
limit = 1
|
||||
body1 = {'secrets': [{'status': 'ACTIVE',
|
||||
'content_types': {'default': 'text/plain'},
|
||||
'updated': '2013-06-03T21:16:58.349230',
|
||||
@@ -162,13 +165,22 @@ class WhenTestingConnection(unittest.TestCase):
|
||||
'7-4090-bbef-bbb6025e5e7b',
|
||||
'expiration': None,
|
||||
'bit_length': None,
|
||||
'mime_type': 'text/plain'}]}
|
||||
'mime_type': 'text/plain'}],
|
||||
'next': "{0}/{1}?limit={2}&offset={2}".format(self.connection.
|
||||
_tenant,
|
||||
self.connection.
|
||||
SECRETS_PATH,
|
||||
limit)}
|
||||
secrets = [client.Secret(self.connection, body1['secrets'][0])]
|
||||
self.request.return_value.content = json.dumps(body1)
|
||||
self.assertTrue(self._are_equivalent(secrets,
|
||||
self.connection.list_secrets()))
|
||||
secret_list, prev_ref, next_ref = self.connection.list_secrets(limit,
|
||||
0)
|
||||
self.assertTrue(self._are_equivalent(secrets, secret_list))
|
||||
self.assertIsNone(prev_ref)
|
||||
self.assertEqual(body1['next'], next_ref)
|
||||
|
||||
def test_list_multiple_secrets(self):
|
||||
limit = 2
|
||||
body1 = {'secrets': [{'status': 'ACTIVE',
|
||||
'content_types': {'default': 'text/plain'},
|
||||
'updated': '2013-06-03T21:16:58.349230',
|
||||
@@ -181,29 +193,43 @@ class WhenTestingConnection(unittest.TestCase):
|
||||
'7-4090-bbef-bbb6025e5e7b',
|
||||
'expiration': None,
|
||||
'bit_length': None,
|
||||
'mime_type': 'text/plain'}]}
|
||||
'mime_type': 'text/plain'}],
|
||||
'previous': "{0}/{1}?limit={2}&offset={2}".format(
|
||||
self.connection._tenant,
|
||||
self.connection.
|
||||
SECRETS_PATH,
|
||||
limit)}
|
||||
|
||||
body2 = body1
|
||||
body2['secrets'][0]['name'] = 'test_2'
|
||||
body2['secrets'][0]['secret_ref'] = 'http://localhost:9311/v1/No'\
|
||||
+ 'ne/secrets/bbd2036f-7307-'\
|
||||
+ '4090-bbef-bbb6025eabcd'
|
||||
body2['previous'] = 'http://localhost:9311/v1/None/secrets/19106'\
|
||||
+ 'b6e-4ef1-48d1-8950-170c1a5838e1'
|
||||
body2['next'] = None
|
||||
|
||||
secrets = [client.Secret(self.connection, b['secrets'][0])
|
||||
for b in (body1, body2)]
|
||||
body2['secrets'].insert(0, body1['secrets'][0])
|
||||
self.request.return_value.content = json.dumps(body2)
|
||||
self.assertTrue(self._are_equivalent(secrets,
|
||||
self.connection.list_secrets()))
|
||||
secret_list, prev_ref, next_ref = self.connection.list_secrets(limit,
|
||||
1)
|
||||
self.assertTrue(self._are_equivalent(secrets, secret_list))
|
||||
self.assertEqual(body2['previous'], prev_ref)
|
||||
self.assertIsNone(next_ref)
|
||||
|
||||
def test_list_no_orders(self):
|
||||
body0 = {'orders': []}
|
||||
orders = []
|
||||
self.request.return_value.content = json.dumps(body0)
|
||||
self.assertTrue(self._are_equivalent(orders,
|
||||
self.connection.list_orders()))
|
||||
order_list, prev_ref, next_ref = self.connection.list_orders(0, 0)
|
||||
self.assertTrue(self._are_equivalent(orders, order_list))
|
||||
self.assertIsNone(prev_ref)
|
||||
self.assertIsNone(next_ref)
|
||||
|
||||
def test_list_single_order(self):
|
||||
limit = 1
|
||||
body1 = {'orders': [{'status': 'PENDING',
|
||||
'updated': '2013-06-05T15:15:30.904760',
|
||||
'created': '2013-06-05T15:15:30.904752',
|
||||
@@ -217,13 +243,21 @@ class WhenTestingConnection(unittest.TestCase):
|
||||
'algorithm': None,
|
||||
'expiration': None,
|
||||
'bit_length': None,
|
||||
'mime_type': 'text/plain'}}]}
|
||||
'mime_type': 'text/plain'}}],
|
||||
'next': "{0}/{1}?limit={2}&offset={2}".format(self.connection.
|
||||
_tenant,
|
||||
self.connection.
|
||||
ORDERS_PATH,
|
||||
limit)}
|
||||
orders = [client.Order(self.connection, body1['orders'][0])]
|
||||
self.request.return_value.content = json.dumps(body1)
|
||||
self.assertTrue(self._are_equivalent(orders,
|
||||
self.connection.list_orders()))
|
||||
order_list, prev_ref, next_ref = self.connection.list_orders(limit, 0)
|
||||
self.assertTrue(self._are_equivalent(orders, order_list))
|
||||
self.assertIsNone(prev_ref)
|
||||
self.assertEqual(body1['next'], next_ref)
|
||||
|
||||
def test_list_multiple_orders(self):
|
||||
limit = 2
|
||||
body1 = {'orders': [{'status': 'PENDING',
|
||||
'updated': '2013-06-05T15:15:30.904760',
|
||||
'created': '2013-06-05T15:15:30.904752',
|
||||
@@ -237,19 +271,34 @@ class WhenTestingConnection(unittest.TestCase):
|
||||
'algorithm': None,
|
||||
'expiration': None,
|
||||
'bit_length': None,
|
||||
'mime_type': 'text/plain'}}]}
|
||||
'mime_type': 'text/plain'}}],
|
||||
'previous': "{0}/{1}?limit={2}&offset={2}".format(
|
||||
self.connection._tenant,
|
||||
self.connection.
|
||||
SECRETS_PATH,
|
||||
limit)}
|
||||
body2 = body1
|
||||
body2['orders'][0]['order_ref'] = 'http://localhost:9311/v1/No'\
|
||||
+ 'ne/orders/9f651441-3ccd-4'\
|
||||
+ '5b3-bc60-3051656382fj'
|
||||
body2['orders'][0]['secret']['name'] = 'test_2'
|
||||
|
||||
body2['orders'][0]['name'] = 'test_2'
|
||||
body2['orders'][0]['secret_ref'] = 'http://localhost:9311/v1/No'\
|
||||
+ 'ne/secrets/bbd2036f-7307-'\
|
||||
+ '4090-bbef-bbb6025eabcd'
|
||||
body2['previous'] = 'http://localhost:9311/v1/None/orders/19106'\
|
||||
+ 'b6e-4ef1-48d1-8950-170c1a5838e1'
|
||||
body2['next'] = None
|
||||
|
||||
orders = [client.Order(self.connection, b['orders'][0])
|
||||
for b in (body1, body2)]
|
||||
body2['orders'].insert(0, body1['orders'][0])
|
||||
self.request.return_value.content = json.dumps(body2)
|
||||
self.assertTrue(self._are_equivalent(orders,
|
||||
self.connection.list_orders()))
|
||||
order_list, prev_ref, next_ref = self.connection.list_orders(limit, 1)
|
||||
self.assertTrue(self._are_equivalent(orders, order_list))
|
||||
self.assertEqual(body2['previous'], prev_ref)
|
||||
self.assertIsNone(next_ref)
|
||||
|
||||
def test_should_get_response(self):
|
||||
self._setup_request()
|
||||
@@ -272,8 +321,11 @@ class WhenTestingConnection(unittest.TestCase):
|
||||
def test_should_raise_exception(self):
|
||||
self._setup_request()
|
||||
self.request.return_value.ok = False
|
||||
with self.assertRaises(ClientException):
|
||||
self.request.return_value.status_code = 404
|
||||
with self.assertRaises(ClientException) as e:
|
||||
self.connection._perform_http('GET', self.href)
|
||||
exception = e.exception
|
||||
self.assertEqual(404, exception.http_status)
|
||||
|
||||
def _setup_request(self):
|
||||
self.request.return_value.headers = {'Accept': 'application/json'}
|
||||
|
||||
8
tox.ini
8
tox.ini
@@ -4,7 +4,7 @@
|
||||
# and then run "tox" from this directory.
|
||||
|
||||
[tox]
|
||||
envlist = py26, py27, py33, pep8
|
||||
envlist = py26, py27
|
||||
|
||||
[testenv]
|
||||
setenv = VIRTUAL_ENV={envdir}
|
||||
@@ -33,3 +33,9 @@ downloadcache = ~/cache/pip
|
||||
ignore = F,H
|
||||
show-source = True
|
||||
exclude = .venv,.tox,dist,doc,*egg
|
||||
|
||||
[testenv:py26]
|
||||
commands = nosetests {posargs:--with-xcoverage --all-modules --cover-inclusive --traverse-namespace --with-xunit --cover-package=barbican}
|
||||
|
||||
[testenv:py27]
|
||||
commands = nosetests {posargs:--with-xcoverage --all-modules --cover-inclusive --traverse-namespace --with-xunit --cover-package=barbican}
|
||||
|
||||
Reference in New Issue
Block a user