Add solum builder client

This client will be used to communicate with builder service from solum.

Generalize KeystoneAuthPlugin so that it can be used by both solumclient and
builder client.

Fixed a bug in solumclient/common/base.py

Change-Id: I86630f40b32c6fcada5aa292fae8e36cecab9908
This commit is contained in:
Noorul Islam K M
2014-03-05 21:59:31 +05:30
parent 878075169f
commit 04fbabadc0
14 changed files with 211 additions and 13 deletions

View File

View File

@@ -0,0 +1,34 @@
# Copyright 2014 - Noorul Islam K M
#
# 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 solumclient.common import auth
from solumclient.openstack.common.apiclient import client
API_NAME = 'builder'
VERSION_MAP = {
'1': 'solumclient.builder.v1.client.Client',
}
def Client(version, **kwargs):
client_class = client.BaseClient.get_class(API_NAME, version, VERSION_MAP)
keystone_auth = auth.KeystoneAuthPlugin(
username=kwargs.get('username'),
password=kwargs.get('password'),
tenant_name=kwargs.get('tenant_name'),
token=kwargs.get('token'),
auth_url=kwargs.get('auth_url'),
endpoint=kwargs.get('endpoint'))
http_client = client.HTTPClient(keystone_auth)
return client_class(http_client)

View File

View File

@@ -0,0 +1,25 @@
# Copyright 2014 - Noorul Islam K M
#
# 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 solumclient.builder.v1 import image
from solumclient.openstack.common.apiclient import client
class Client(client.BaseClient):
"""Client for the Solum v1 API."""
def __init__(self, http_client, extensions=None):
"""Initialize a new client for the Builder v1 API."""
super(Client, self).__init__(http_client, extensions)
self.images = image.ImageManager(self)

View File

@@ -0,0 +1,33 @@
# Copyright 2014 - Noorul Islam K M
#
# 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 solumclient.common import base as solum_base
from solumclient.openstack.common.apiclient import base as apiclient_base
class Image(apiclient_base.Resource):
def __repr__(self):
return "<Image %s>" % self._info
class ImageManager(solum_base.CrudManager):
resource_class = Image
collection_key = 'images'
key = 'image'
def create(self, **kwargs):
return super(ImageManager, self).create(base_url="/v1", **kwargs)
def get(self, **kwargs):
return super(ImageManager, self).get(base_url="/v1", **kwargs)

View File

@@ -29,7 +29,7 @@ def Client(version, **kwargs):
tenant_name=kwargs.get('tenant_name'),
token=kwargs.get('token'),
auth_url=kwargs.get('auth_url'),
solum_url=kwargs.get('solum_url'))
endpoint=kwargs.get('endpoint'))
http_client = client.HTTPClient(keystone_auth)
return client_class(http_client)
@@ -41,7 +41,7 @@ def get_client(api_version, **kwargs):
:param api_version: the API version to use
:param kwargs: keyword args containing credentials, either:
* os_auth_token: pre-existing token to re-use
* solum_url: solum API endpoint
* endpoint: solum API endpoint
or:
* os_username: name of user
* os_password: user's password
@@ -54,7 +54,7 @@ def get_client(api_version, **kwargs):
'tenant_name': kwargs.get('os_tenant_name'),
'token': kwargs.get('os_auth_token'),
'auth_url': kwargs.get('os_auth_url'),
'solum_url': kwargs.get('solum_url')
'endpoint': kwargs.get('solum_url')
}
return Client(api_version, **cli_kwargs)

View File

@@ -26,7 +26,7 @@ class KeystoneAuthPlugin(auth.BaseAuthPlugin):
"tenant_name",
"token",
"auth_url",
"solum_url"
"endpoint"
]
def _do_authenticate(self, http_client):
@@ -43,13 +43,13 @@ class KeystoneAuthPlugin(auth.BaseAuthPlugin):
def token_and_endpoint(self, endpoint_type, service_type):
token = endpoint = None
if self.opts.get('token') and self.opts.get('solum_url'):
if self.opts.get('token') and self.opts.get('endpoint'):
token = self.opts.get('token')
endpoint = self.opts.get('solum_url')
endpoint = self.opts.get('endpoint')
elif hasattr(self, '_ksclient'):
token = self._ksclient.auth_token
endpoint = (self.opts.get('solum_url') or
endpoint = (self.opts.get('endpoint') or
self._ksclient.service_catalog.url_for(
service_type=service_type,
endpoint_type=endpoint_type))
@@ -63,7 +63,7 @@ class KeystoneAuthPlugin(auth.BaseAuthPlugin):
"""
if self.opts.get('token'):
lookup_table = ["token", "solum_url"]
lookup_table = ["token", "endpoint"]
else:
lookup_table = ["username", "password", "tenant_name", "auth_url"]

View File

@@ -114,5 +114,4 @@ class CrudManager(ManagerMixin, base.CrudManager):
def create(self, **kwargs):
kwargs = self._filter_kwargs(kwargs)
return self._post(
self.build_url(**kwargs),
{self.key: kwargs})
self.build_url(**kwargs), kwargs)

View File

@@ -76,7 +76,6 @@ class CommandsBase(object):
# Remove arguments that are not to be passed to the client in this
# case.
del client_args['os_auth_token']
del client_args['solum_url']
if not parsed.os_username:
raise exc.CommandError("You must provide a username via "
@@ -98,6 +97,10 @@ class CommandsBase(object):
"either --os-auth-url or via "
"env[OS_AUTH_URL]")
else:
client_args['endpoint'] = client_args['solum_url']
del client_args['solum_url']
self.client = solum_client.get_client(parsed.solum_api_version,
**client_args)

View File

View File

@@ -0,0 +1,31 @@
# Copyright 2014 - Noorul Islam K M
#
# 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.
import mock
from solumclient.builder import client
from solumclient.common import auth
from solumclient.openstack.common.apiclient import exceptions
from solumclient.tests import base
class ClientTest(base.TestCase):
def test_client_unsupported_version(self):
self.assertRaises(exceptions.UnsupportedVersion,
client.Client, '111.11', **{})
def test_client(self):
with mock.patch.object(auth, 'KeystoneAuthPlugin'):
client.Client('1', **{})

View File

View File

@@ -0,0 +1,73 @@
# Copyright 2014 - Noorul Islam K M
#
# 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 solumclient.builder.v1 import client as builder_client
from solumclient.builder.v1 import image
from solumclient.openstack.common.apiclient import fake_client
from solumclient.tests import base
image_fixture = {
'uri': 'http://example.com/v1/images/i1',
'name': 'php-web-app',
'source_uri': 'git://example.com/project/app.git',
'type': 'image',
'description': 'A php web application',
'tags': ['small'],
'project_id': '1dae5a09ef2b4d8cbf3594b0eb4f6b94',
'user_id': '55f41cf46df74320b9486a35f5d28a11',
}
fixtures_get = {
'/v1/images/i1': {
'GET': (
{},
image_fixture
),
}
}
fixtures_create = {
'/v1/images': {
'POST': (
{},
image_fixture
),
}
}
class ImageManagerTest(base.TestCase):
def test_create(self):
fake_http_client = fake_client.FakeHTTPClient(fixtures=fixtures_create)
api_client = builder_client.Client(fake_http_client)
mgr = image.ImageManager(api_client)
image_obj = mgr.create()
self.assertIn('Image', repr(image_obj))
self.assertEqual(image_obj.uri, image_fixture['uri'])
self.assertEqual(image_obj.type, image_fixture['type'])
self.assertEqual(image_obj.project_id, image_fixture['project_id'])
self.assertEqual(image_obj.user_id, image_fixture['user_id'])
def test_get(self):
fake_http_client = fake_client.FakeHTTPClient(fixtures=fixtures_get)
api_client = builder_client.Client(fake_http_client)
mgr = image.ImageManager(api_client)
image_obj = mgr.get(image_id='i1')
self.assertIn('Image', repr(image_obj))
self.assertEqual(image_obj.uri, image_fixture['uri'])
self.assertEqual(image_obj.type, image_fixture['type'])
self.assertEqual(image_obj.project_id, image_fixture['project_id'])
self.assertEqual(image_obj.user_id, image_fixture['user_id'])

View File

@@ -29,7 +29,7 @@ class KeystoneAuthPluginTest(base.TestCase):
password="fake-password",
tenant_name="fake-tenant-name",
auth_url="http://auth",
solum_url="http://solum")
endpoint="http://solum")
self.cs = client.HTTPClient(auth_plugin=plugin)
def test_authenticate(self, mock_ksclient):
@@ -59,7 +59,7 @@ class KeystoneAuthPluginTokenTest(base.TestCase):
def test_token_and_endpoint(self, mock_ksclient):
plugin = auth.KeystoneAuthPlugin(
token="fake-token",
solum_url="http://solum")
endpoint="http://solum")
cs = client.HTTPClient(auth_plugin=plugin)
cs.authenticate()