From ca767856b600f2f14243b0979f706b78635996fd Mon Sep 17 00:00:00 2001 From: Jenkins Date: Feb 28 2012 07:07:59 +0000 Subject: Merge "Endpoints: Add create, delete, list support" --- diff --git a/keystoneclient/v2_0/client.py b/keystoneclient/v2_0/client.py index 3fd8f3a..a609b87 100644 --- a/keystoneclient/v2_0/client.py +++ b/keystoneclient/v2_0/client.py @@ -18,6 +18,7 @@ from keystoneclient import client from keystoneclient import exceptions from keystoneclient import service_catalog from keystoneclient.v2_0 import ec2 +from keystoneclient.v2_0 import endpoints from keystoneclient.v2_0 import roles from keystoneclient.v2_0 import services from keystoneclient.v2_0 import tenants @@ -63,6 +64,7 @@ class Client(client.HTTPClient): def __init__(self, endpoint=None, **kwargs): """ Initialize a new client for the Keystone v2.0 API. """ super(Client, self).__init__(endpoint=endpoint, **kwargs) + self.endpoints = endpoints.EndpointManager(self) self.roles = roles.RoleManager(self) self.services = services.ServiceManager(self) self.tenants = tenants.TenantManager(self) diff --git a/keystoneclient/v2_0/endpoints.py b/keystoneclient/v2_0/endpoints.py new file mode 100644 index 0000000..73e58b4 --- /dev/null +++ b/keystoneclient/v2_0/endpoints.py @@ -0,0 +1,39 @@ +# Copyright 2012 Canonical Ltd. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from keystoneclient import base + + +class Endpoint(base.Resource): + def __repr__(self): + return "" % self._info + + +class EndpointManager(base.ManagerWithFind): + resource_class = Endpoint + + def list(self): + return self._list('/endpoints', 'endpoints') + + def create(self, region, service_id, publicurl, adminurl, internalurl): + body = {'endpoint': {'region': region, + 'service_id': service_id, + 'publicurl': publicurl, + 'adminurl': adminurl, + 'internalurl': internalurl}} + return self._create('/endpoints', body, 'endpoint') + + def delete(self, id): + return self._delete('/endpoints/%s' % id) diff --git a/keystoneclient/v2_0/shell.py b/keystoneclient/v2_0/shell.py index 8d00f2a..6825b16 100755 --- a/keystoneclient/v2_0/shell.py +++ b/keystoneclient/v2_0/shell.py @@ -305,6 +305,45 @@ def do_endpoint_get(kc, args): utils.print_dict({'%s.%s' % (args.service, args.endpoint_type): url}) +def do_endpoint_list(kc, args): + endpoints = kc.endpoints.list() + utils.print_list(endpoints, + ['id', 'region', 'publicurl', 'internalurl', 'publicurl']) + + +@utils.arg('--region', metavar='', + help='Endpoint region', nargs='?', default='regionOne') +@utils.arg('--service_id', metavar='', + help='ID of service associated with Endpoint', nargs='?') +@utils.arg('--publicurl', metavar='', + help='Public URL endpoint', nargs='?') +@utils.arg('--adminurl', metavar='', + help='Admin URL endpoint', nargs='?') +@utils.arg('--internalurl', metavar='', + help='Internal URL endpoint', nargs='?') +def do_endpoint_create(kc, args): + kwargs = { + 'region': args.region, + 'service_id': args.service_id, + 'publicurl': args.publicurl, + 'adminurl': args.adminurl, + 'internalurl': args.internalurl, + } + endpoint = kc.endpoints.create( + args.region, args.service_id, args.publicurl, + args.adminurl, args.internalurl) + utils.print_dict(endpoint._info) + + +@utils.arg('id', metavar='', help='ID of endpoint to delete') +def do_endpoint_delete(kc, args): + try: + kc.endpoints.delete(args.id) + print 'Endpoint has been deleted.' + except: + print 'Unable to delete endpoint.' + + def do_token_get(kc, args): """Display the current user token""" utils.print_dict(kc.service_catalog.get_token()) diff --git a/tests/v2_0/test_endpoints.py b/tests/v2_0/test_endpoints.py new file mode 100644 index 0000000..d810f03 --- /dev/null +++ b/tests/v2_0/test_endpoints.py @@ -0,0 +1,117 @@ +import urlparse +import json + +import httplib2 + +from keystoneclient.v2_0 import endpoints +from tests import utils + + +class EndpointTests(utils.TestCase): + def setUp(self): + super(EndpointTests, self).setUp() + self.TEST_REQUEST_HEADERS = {'X-Auth-Token': 'aToken', + 'User-Agent': 'python-keystoneclient'} + self.TEST_POST_HEADERS = {'Content-Type': 'application/json', + 'X-Auth-Token': 'aToken', + 'User-Agent': 'python-keystoneclient'} + self.TEST_ENDPOINTS = {'endpoints': [ + { + 'adminurl': + 'http://host-1:8774/v1.1/$(tenant_id)s', + 'id': + '8f9531231e044e218824b0e58688d262', + 'internalurl': + 'http://host-1:8774/v1.1/$(tenant_id)s', + 'publicurl': + 'http://host-1:8774/v1.1/$(tenant_id)s', + 'region': + 'RegionOne' + }, + { + 'adminurl': + 'http://host-1:8774/v1.1/$(tenant_id)s', + 'id': + '8f9531231e044e218824b0e58688d263', + 'internalurl': + 'http://host-1:8774/v1.1/$(tenant_id)s', + 'publicurl': + 'http://host-1:8774/v1.1/$(tenant_id)s', + 'region': + 'RegionOne' + } + ] + } + + def test_create(self): + req_body = {"endpoint": {"region": "RegionOne", + "publicurl": + "http://host-3:8774/v1.1/$(tenant_id)s", + "internalurl": + "http://host-3:8774/v1.1/$(tenant_id)s", + "adminurl": + "http://host-3:8774/v1.1/$(tenant_id)s", + "service_id": "e044e21"}} + + resp_body = {"endpoint": { + "adminurl": + "http://host-3:8774/v1.1/$(tenant_id)s", + "region": "RegionOne", + "id": "1fd485b2ffd54f409a5ecd42cba11401", + "internalurl": + "http://host-3:8774/v1.1/$(tenant_id)s", + "publicurl": + "http://host-3:8774/v1.1/$(tenant_id)s"}} + + resp = httplib2.Response({ + "status": 200, + "body": json.dumps(resp_body), + }) + + httplib2.Http.request(urlparse.urljoin(self.TEST_URL, + 'v2.0/endpoints'), + 'POST', + body=json.dumps(req_body), + headers=self.TEST_POST_HEADERS) \ + .AndReturn((resp, resp['body'])) + self.mox.ReplayAll() + + endpoint = self.client.endpoints.create( + region=req_body['endpoint']['region'], + publicurl=req_body['endpoint']['publicurl'], + adminurl=req_body['endpoint']['adminurl'], + internalurl=req_body['endpoint']['internalurl'], + service_id=req_body['endpoint']['service_id'] + ) + self.assertTrue(isinstance(endpoint, endpoints.Endpoint)) + + def test_delete(self): + resp = httplib2.Response({ + "status": 200, + "body": "" + }) + httplib2.Http.request(urlparse.urljoin(self.TEST_URL, + 'v2.0/endpoints/8f953'), + 'DELETE', + headers=self.TEST_REQUEST_HEADERS) \ + .AndReturn((resp, resp['body'])) + self.mox.ReplayAll() + + self.client.endpoints.delete('8f953') + + def test_list(self): + resp = httplib2.Response({ + "status": 200, + "body": json.dumps(self.TEST_ENDPOINTS), + }) + + httplib2.Http.request(urlparse.urljoin(self.TEST_URL, + 'v2.0/endpoints?fresh=1234'), + 'GET', + headers=self.TEST_REQUEST_HEADERS) \ + .AndReturn((resp, resp['body'])) + self.mox.ReplayAll() + + endpoint_list = self.client.endpoints.list() + [self.assertTrue(isinstance(r, endpoints.Endpoint)) \ + for r in endpoint_list]