Add initial solum client code
This includes: 1. A client based on oslo apiclient. 2. Platform manager for platform resource. blueprint solum-cli Change-Id: I4e40b7b86a498b24ec9ea1eadaf770eda611aaca
This commit is contained in:
@@ -2,3 +2,6 @@ pbr>=0.5.21,<1.0
|
||||
Babel>=1.3
|
||||
oslo.config>=1.2.0
|
||||
iso8601>=0.1.8
|
||||
requests>=1.1
|
||||
python-keystoneclient>=0.4.2
|
||||
stevedore>=0.12
|
||||
|
34
solumclient/client.py
Normal file
34
solumclient/client.py
Normal file
@@ -0,0 +1,34 @@
|
||||
# Copyright 2013 - 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 = 'solum'
|
||||
VERSION_MAP = {
|
||||
'1': 'solumclient.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'),
|
||||
solum_url=kwargs.get('solum_url'))
|
||||
http_client = client.HTTPClient(keystone_auth)
|
||||
return client_class(http_client)
|
0
solumclient/common/__init__.py
Normal file
0
solumclient/common/__init__.py
Normal file
74
solumclient/common/auth.py
Normal file
74
solumclient/common/auth.py
Normal file
@@ -0,0 +1,74 @@
|
||||
# Copyright 2013 - 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 keystoneclient.v2_0 import client as ksclient
|
||||
|
||||
from solumclient.openstack.common.apiclient import auth
|
||||
from solumclient.openstack.common.apiclient import exceptions
|
||||
|
||||
|
||||
class KeystoneAuthPlugin(auth.BaseAuthPlugin):
|
||||
|
||||
opt_names = [
|
||||
"username",
|
||||
"password",
|
||||
"tenant_name",
|
||||
"token",
|
||||
"auth_url",
|
||||
"solum_url"
|
||||
]
|
||||
|
||||
def _do_authenticate(self, http_client):
|
||||
if self.opts.get('token') is None:
|
||||
ks_kwargs = {
|
||||
'username': self.opts.get('username'),
|
||||
'password': self.opts.get('password'),
|
||||
'tenant_name': self.opts.get('tenant_name'),
|
||||
'auth_url': self.opts.get('auth_url'),
|
||||
}
|
||||
|
||||
self._ksclient = ksclient.Client(**ks_kwargs)
|
||||
|
||||
def token_and_endpoint(self, endpoint_type, service_type):
|
||||
token = endpoint = None
|
||||
|
||||
if self.opts.get('token') and self.opts.get('solum_url'):
|
||||
token = self.opts.get('token')
|
||||
endpoint = self.opts.get('solum_url')
|
||||
|
||||
elif hasattr(self, '_ksclient'):
|
||||
token = self._ksclient.auth_token
|
||||
endpoint = (self.opts.get('solum_url') or
|
||||
self._ksclient.service_catalog.url_for(
|
||||
service_type=service_type,
|
||||
endpoint_type=endpoint_type))
|
||||
|
||||
return (token, endpoint)
|
||||
|
||||
def sufficient_options(self):
|
||||
"""Check if all required options are present.
|
||||
|
||||
:raises: AuthPluginOptionsMissing
|
||||
"""
|
||||
|
||||
if self.opts.get('token'):
|
||||
lookup_table = ["token", "solum_url"]
|
||||
else:
|
||||
lookup_table = ["username", "password", "tenant_name", "auth_url"]
|
||||
|
||||
missing = [opt
|
||||
for opt in lookup_table
|
||||
if not self.opts.get(opt)]
|
||||
if missing:
|
||||
raise exceptions.AuthPluginOptionsMissing(missing)
|
33
solumclient/common/base.py
Normal file
33
solumclient/common/base.py
Normal file
@@ -0,0 +1,33 @@
|
||||
# Copyright 2013 - 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.openstack.common.apiclient import base
|
||||
|
||||
|
||||
class BaseManager(base.BaseManager):
|
||||
def _get(self, url, response_key=None):
|
||||
"""Get an object from collection.
|
||||
|
||||
:param url: a partial URL, e.g., '/servers'
|
||||
:param response_key: the key to be looked up in response dictionary,
|
||||
e.g., 'server'
|
||||
"""
|
||||
body = self.client.get(url).json()
|
||||
|
||||
if response_key is None:
|
||||
data = body
|
||||
else:
|
||||
data = body[response_key]
|
||||
|
||||
return self.resource_class(self, data, loaded=True)
|
0
solumclient/tests/common/__init__.py
Normal file
0
solumclient/tests/common/__init__.py
Normal file
69
solumclient/tests/common/test_auth.py
Normal file
69
solumclient/tests/common/test_auth.py
Normal file
@@ -0,0 +1,69 @@
|
||||
# Copyright 2013 - 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 keystoneclient.v2_0 import client as ksclient
|
||||
import mock
|
||||
|
||||
from solumclient.common import auth
|
||||
from solumclient.openstack.common.apiclient import client
|
||||
from solumclient.tests import base
|
||||
|
||||
|
||||
@mock.patch.object(ksclient, 'Client')
|
||||
class KeystoneAuthPluginTest(base.TestCase):
|
||||
def setUp(self):
|
||||
super(KeystoneAuthPluginTest, self).setUp()
|
||||
plugin = auth.KeystoneAuthPlugin(
|
||||
username="fake-username",
|
||||
password="fake-password",
|
||||
tenant_name="fake-tenant-name",
|
||||
auth_url="http://auth",
|
||||
solum_url="http://solum")
|
||||
self.cs = client.HTTPClient(auth_plugin=plugin)
|
||||
|
||||
def test_authenticate(self, mock_ksclient):
|
||||
self.cs.authenticate()
|
||||
mock_ksclient.assert_called_with(
|
||||
username="fake-username",
|
||||
password="fake-password",
|
||||
tenant_name="fake-tenant-name",
|
||||
auth_url="http://auth")
|
||||
|
||||
def test_token_and_endpoint(self, mock_ksclient):
|
||||
self.cs.authenticate()
|
||||
(token, endpoint) = self.cs.auth_plugin.token_and_endpoint(
|
||||
"fake-endpoint-type", "fake-service-type")
|
||||
self.assertIsInstance(token, mock.MagicMock)
|
||||
self.assertEqual(endpoint, "http://solum")
|
||||
|
||||
def test_token_and_endpoint_before_auth(self, mock_ksclient):
|
||||
(token, endpoint) = self.cs.auth_plugin.token_and_endpoint(
|
||||
"fake-endpoint-type", "fake-service-type")
|
||||
self.assertIsNone(token, None)
|
||||
self.assertIsNone(endpoint, None)
|
||||
|
||||
|
||||
@mock.patch.object(ksclient, 'Client')
|
||||
class KeystoneAuthPluginTokenTest(base.TestCase):
|
||||
def test_token_and_endpoint(self, mock_ksclient):
|
||||
plugin = auth.KeystoneAuthPlugin(
|
||||
token="fake-token",
|
||||
solum_url="http://solum")
|
||||
cs = client.HTTPClient(auth_plugin=plugin)
|
||||
|
||||
cs.authenticate()
|
||||
(token, endpoint) = cs.auth_plugin.token_and_endpoint(
|
||||
"fake-endpoint-type", "fake-service-type")
|
||||
self.assertEqual(token, 'fake-token')
|
||||
self.assertEqual(endpoint, 'http://solum')
|
76
solumclient/tests/common/test_base.py
Normal file
76
solumclient/tests/common/test_base.py
Normal file
@@ -0,0 +1,76 @@
|
||||
# Copyright 2013 - 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
|
||||
from solumclient.openstack.common.apiclient import client
|
||||
from solumclient.openstack.common.apiclient import fake_client
|
||||
from solumclient.tests import base as test_base
|
||||
|
||||
|
||||
fixture1 = {
|
||||
'/foo_resource': {
|
||||
'GET': (
|
||||
{},
|
||||
{'id': 1, 'name': 'foo'}
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fixture2 = {
|
||||
'/foo_resource': {
|
||||
'GET': (
|
||||
{},
|
||||
{'foo_resource': {'id': 1, 'name': 'foo'}}
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class FooResource(apiclient_base.Resource):
|
||||
pass
|
||||
|
||||
|
||||
class FooResourceManager(solum_base.BaseManager):
|
||||
resource_class = FooResource
|
||||
|
||||
def get(self):
|
||||
return self._get("/foo_resource")
|
||||
|
||||
def get_with_response_key(self):
|
||||
return self._get("/foo_resource", "foo_resource")
|
||||
|
||||
|
||||
class TestClient(client.BaseClient):
|
||||
|
||||
service_type = "test"
|
||||
|
||||
def __init__(self, http_client, extensions=None):
|
||||
super(TestClient, self).__init__(
|
||||
http_client, extensions=extensions)
|
||||
|
||||
self.foo_resource = FooResourceManager(self)
|
||||
|
||||
|
||||
class BaseManagerTest(test_base.TestCase):
|
||||
|
||||
def test_get(self):
|
||||
http_client = fake_client.FakeHTTPClient(fixtures=fixture1)
|
||||
tc = TestClient(http_client)
|
||||
tc.foo_resource.get()
|
||||
|
||||
def test_get_with_response_key(self):
|
||||
http_client = fake_client.FakeHTTPClient(fixtures=fixture2)
|
||||
tc = TestClient(http_client)
|
||||
tc.foo_resource.get_with_response_key()
|
31
solumclient/tests/test_client.py
Normal file
31
solumclient/tests/test_client.py
Normal file
@@ -0,0 +1,31 @@
|
||||
# Copyright 2013 - 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 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', **{})
|
0
solumclient/tests/v1/__init__.py
Normal file
0
solumclient/tests/v1/__init__.py
Normal file
62
solumclient/tests/v1/test_platform.py
Normal file
62
solumclient/tests/v1/test_platform.py
Normal file
@@ -0,0 +1,62 @@
|
||||
# Copyright 2013 - 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.openstack.common.apiclient import fake_client
|
||||
from solumclient.tests import base
|
||||
from solumclient.v1 import client as solumclient
|
||||
from solumclient.v1 import platform
|
||||
|
||||
|
||||
fixtures = {
|
||||
'/v1': {
|
||||
'GET': (
|
||||
{},
|
||||
{
|
||||
'uri': 'http://example.com/v1',
|
||||
'name': 'solum',
|
||||
'type': 'platform',
|
||||
'tags': ['solid'],
|
||||
'project_id': '1dae5a09ef2b4d8cbf3594b0eb4f6b94',
|
||||
'user_id': '55f41cf46df74320b9486a35f5d28a11',
|
||||
'description': 'solum native implementation',
|
||||
'implementation_version': '2014.1.1',
|
||||
'assemblies_uri': 'http://example.com:9777/v1/assemblies',
|
||||
'services_uri': 'http://example.com:9777/v1/services',
|
||||
'components_uri': 'http://example.com:9777/v1/components',
|
||||
'extenstions_uri': 'http://example.com:9777/v1/extenstions'
|
||||
}
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class PlatformManagerTest(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(PlatformManagerTest, self).setUp()
|
||||
fake_http_client = fake_client.FakeHTTPClient(fixtures=fixtures)
|
||||
api_client = solumclient.Client(fake_http_client)
|
||||
self.mgr = platform.PlatformManager(api_client)
|
||||
|
||||
def test_get(self):
|
||||
platform = self.mgr.get()
|
||||
self.assertIn('Platform', repr(platform))
|
||||
self.assertEqual(platform.uri,
|
||||
'http://example.com/v1')
|
||||
self.assertEqual(platform.type,
|
||||
'platform')
|
||||
self.assertEqual(platform.project_id,
|
||||
'1dae5a09ef2b4d8cbf3594b0eb4f6b94')
|
||||
self.assertEqual(platform.user_id,
|
||||
'55f41cf46df74320b9486a35f5d28a11')
|
0
solumclient/v1/__init__.py
Normal file
0
solumclient/v1/__init__.py
Normal file
25
solumclient/v1/client.py
Normal file
25
solumclient/v1/client.py
Normal file
@@ -0,0 +1,25 @@
|
||||
# Copyright 2013 - 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.openstack.common.apiclient import client
|
||||
from solumclient.v1 import platform
|
||||
|
||||
|
||||
class Client(client.BaseClient):
|
||||
"""Client for the Solum v1 API."""
|
||||
|
||||
def __init__(self, http_client, extensions=None):
|
||||
"""Initialize a new client for the Solum v1 API."""
|
||||
super(Client, self).__init__(http_client, extensions)
|
||||
self.platform = platform.PlatformManager(self)
|
28
solumclient/v1/platform.py
Normal file
28
solumclient/v1/platform.py
Normal file
@@ -0,0 +1,28 @@
|
||||
# Copyright 2013 - 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 Platform(apiclient_base.Resource):
|
||||
def __repr__(self):
|
||||
return "<Platform %s>" % self._info
|
||||
|
||||
|
||||
class PlatformManager(solum_base.BaseManager):
|
||||
resource_class = Platform
|
||||
|
||||
def get(self, **kwargs):
|
||||
return self._get('/v1')
|
@@ -9,3 +9,4 @@ oslo.sphinx
|
||||
testrepository>=0.0.17
|
||||
testscenarios>=0.4
|
||||
testtools>=0.9.32
|
||||
mock>=1.0
|
||||
|
Reference in New Issue
Block a user