diff options
author | Mike Fedosin <mfedosin@mirantis.com> | 2015-06-09 22:14:03 +0300 |
---|---|---|
committer | Mike Fedosin <mfedosin@mirantis.com> | 2015-08-26 20:02:10 +0300 |
commit | 5d847b92cdf62596dc0448adf85a797f82b51d0d (patch) | |
tree | c6736f1164e73dc962f78e4c9031bc966000d7df | |
parent | 24a7448c650fc302ccbb5d01e4a129d889f7cb0d (diff) | |
download | python-glanceclient-5d847b92cdf62596dc0448adf85a797f82b51d0d.tar.gz |
Glance v3 client initial commit
This commit provides initial support for Glance v3 api and
creates stubs for methods.
FastTrack
Implements-blueprint: artifact-repository
Change-Id: I83bf3eed4e2c44687f001e98be264fa75f16b349
-rw-r--r-- | glanceclient/tests/unit/v3/__init__.py | 37 | ||||
-rw-r--r-- | glanceclient/tests/unit/v3/test_artifact_type.py | 88 | ||||
-rw-r--r-- | glanceclient/tests/unit/v3/test_artifacts.py | 28 | ||||
-rw-r--r-- | glanceclient/v3/__init__.py | 59 | ||||
-rw-r--r-- | glanceclient/v3/artifacts.py | 91 | ||||
-rw-r--r-- | glanceclient/v3/client.py | 41 |
6 files changed, 344 insertions, 0 deletions
diff --git a/glanceclient/tests/unit/v3/__init__.py b/glanceclient/tests/unit/v3/__init__.py new file mode 100644 index 0000000..c3e5f95 --- /dev/null +++ b/glanceclient/tests/unit/v3/__init__.py @@ -0,0 +1,37 @@ +# Copyright (c) 2015 Mirantis, Inc. +# +# 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 oslo_utils import timeutils + + +def get_artifact_fixture(**kwargs): + ts = timeutils.strtime() + fixture = { + "id": "123", + "version": "11.2", + "description": "by far, the most evil thing I've encountered", + "name": "Gunter The Penguin", + "visibility": "private", + "state": "creating", + "owner": "Ice King", + "created_at": ts, + "updated_at": ts, + "deleted_at": None, + "published_at": None, + "tags": ["bottle", "egg"], + "type_name": "ice_kingdom", + "type_version": '1.0.1' + } + fixture.update(kwargs) + return fixture diff --git a/glanceclient/tests/unit/v3/test_artifact_type.py b/glanceclient/tests/unit/v3/test_artifact_type.py new file mode 100644 index 0000000..726db85 --- /dev/null +++ b/glanceclient/tests/unit/v3/test_artifact_type.py @@ -0,0 +1,88 @@ +# Copyright (c) 2015 Mirantis, Inc. +# +# 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 testtools + +from glanceclient.tests.unit.v3 import get_artifact_fixture +from glanceclient.v3 import ArtifactType + + +class TestController(testtools.TestCase): + def test_basic_create(self): + """Create basic artifact without additional properties""" + + artifact = ArtifactType(**get_artifact_fixture()) + self.assertEqual("123", artifact.id) + + def test_additional_properties(self): + """Create artifact with additional properties""" + + type_specific_properties = {"Lemongrab": 3, + "Princess": "Bubblegum", + "Candy people": ["Peppermint Butler", + "Starchie", + "Cinnamon Bun"]} + artifact = ArtifactType(**get_artifact_fixture( + **type_specific_properties)) + self.assertEqual(type_specific_properties, + artifact.type_specific_properties) + + def test_one_dependency(self): + """Create artifact with one dependency""" + + inner_object = get_artifact_fixture(id="1000") + artifact_fixture = get_artifact_fixture(dep=inner_object) + artifact = ArtifactType(**artifact_fixture) + self.assertEqual("1000", artifact.type_specific_properties['dep'].id) + + def test_list_dependencies(self): + """Create artifact with a list of dependencies""" + + dependencies = [get_artifact_fixture(id=str(i)) for i in range(1000, + 1010)] + + artifact_fixture = get_artifact_fixture(dep_list=dependencies) + artifact = ArtifactType(**artifact_fixture) + self.assertEqual(10, + len(artifact.type_specific_properties['dep_list'])) + i = 1000 + for dep in artifact.type_specific_properties['dep_list']: + self.assertEqual(str(i), dep.id) + i += 1 + + def test_invalid_dependency(self): + """Create artifact with invalid dependency as a regular dict""" + + bad_inner_object = get_artifact_fixture(id="1000") + del bad_inner_object['owner'] + good_inner_object = get_artifact_fixture(id="1001") + + artifact_fixture = get_artifact_fixture(bad_dep=bad_inner_object, + good_dep=good_inner_object) + artifact = ArtifactType(**artifact_fixture) + self.assertIsInstance(artifact.type_specific_properties['bad_dep'], + dict) + self.assertIsInstance(artifact.type_specific_properties['good_dep'], + ArtifactType) + + def test_invalid_dependencies_list(self): + """Create artifact with list of dependencies with one invalid""" + dependencies = [get_artifact_fixture(id=str(i)) for i in range(1000, + 1010)] + + del dependencies[9]['owner'] + artifact_fixture = get_artifact_fixture(bad_dep_list=dependencies) + artifact = ArtifactType(**artifact_fixture) + for dep in artifact.type_specific_properties['bad_dep_list']: + self.assertIsInstance(dep, dict) diff --git a/glanceclient/tests/unit/v3/test_artifacts.py b/glanceclient/tests/unit/v3/test_artifacts.py new file mode 100644 index 0000000..0d09ec9 --- /dev/null +++ b/glanceclient/tests/unit/v3/test_artifacts.py @@ -0,0 +1,28 @@ +# Copyright (c) 2015 Mirantis, Inc. +# +# 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 testtools + +from glanceclient.tests import utils +from glanceclient.v3 import artifacts + + +data_fixtures = {} + + +class TestController(testtools.TestCase): + def setUp(self): + super(TestController, self).setUp() + self.api = utils.FakeAPI(data_fixtures) + self.controller = artifacts.Controller(self.api) diff --git a/glanceclient/v3/__init__.py b/glanceclient/v3/__init__.py new file mode 100644 index 0000000..27d99b5 --- /dev/null +++ b/glanceclient/v3/__init__.py @@ -0,0 +1,59 @@ +# Copyright (c) 2015 Mirantis, Inc. +# +# 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 six + +from glanceclient import exc + + +class ArtifactType(object): + generic_properties = ('created_at', 'id', 'name', 'owner', 'state', + 'type_name', 'type_version', 'updated_at', + 'version', 'visibility', 'description', 'tags', + 'published_at', 'deleted_at') + + def __init__(self, **kwargs): + try: + for prop in self.generic_properties: + setattr(self, prop, kwargs.pop(prop)) + except KeyError: + msg = "Invalid parameters were provided" + raise exc.HTTPBadRequest(msg) + self.type_specific_properties = {} + for key, value in six.iteritems(kwargs): + try: + if _is_dependency(value): + + self.type_specific_properties[key] = ArtifactType(**value) + elif _is_dependencies_list(value): + + self.type_specific_properties[key] = [ArtifactType(**elem) + for elem in value] + else: + self.type_specific_properties[key] = value + except exc.HTTPBadRequest: + # if it's not possible to generate artifact object then + # assign the value as a regular dict. + self.type_specific_properties[key] = value + + +def _is_dependency(d): + if type(d) is dict and d.get('type_name') and d.get('type_version'): + return True + return False + + +def _is_dependencies_list(l): + if type(l) is list and all(_is_dependency(d) for d in l): + return True + return False diff --git a/glanceclient/v3/artifacts.py b/glanceclient/v3/artifacts.py new file mode 100644 index 0000000..0ddd308 --- /dev/null +++ b/glanceclient/v3/artifacts.py @@ -0,0 +1,91 @@ +# Copyright (c) 2015 Mirantis, Inc. +# +# 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 glanceclient import exc + + +class Controller(object): + def __init__(self, http_client, type_name=None, type_version=None): + self.http_client = http_client + self.type_name = type_name + self.type_version = type_version + + def _check_type_params(self, type_name, type_version): + """Check that type name and type versions were specified""" + type_name = type_name or self.type_name + type_version = type_version or self.type_version + + if type_name is None: + msg = "Type name must be specified" + raise exc.HTTPBadRequest(msg) + + if type_version is None: + msg = "Type version must be specified" + raise exc.HTTPBadRequest(msg) + + return type_name, type_version + + def create(self, name, version, type_name=None, type_version=None, + **kwargs): + raise NotImplementedError() + + def update(self, artifact_id, type_name=None, type_version=None, + remove_props=None, **kwargs): + raise NotImplementedError() + + def get(self, artifact_id, type_name=None, type_version=None, + show_level=None): + raise NotImplementedError() + + def list(self, type_name=None, type_version=None, **kwargs): + raise NotImplementedError() + + def active(self, artifact_id, type_name=None, type_version=None): + raise NotImplementedError() + + def deactivate(self, artifact_id, type_name=None, type_version=None): + raise NotImplementedError() + + def delete(self, artifact_id, type_name=None, type_version=None): + raise NotImplementedError() + + def upload_blob(self, artifact_id, blob_property, data, position=None, + type_name=None, type_version=None): + raise NotImplementedError() + + def download_blob(self, artifact_id, blob_property, position=None, + type_name=None, type_version=None, do_checksum=True): + raise NotImplementedError() + + def delete_blob(self, artifact_id, blob_property, position=None, + type_name=None, type_version=None): + raise NotImplementedError() + + def add_property(self, artifact_id, dependency_id, position=None, + type_name=None, type_version=None): + raise NotImplementedError() + + def replace_property(self, artifact_id, dependency_id, position=None, + type_name=None, type_version=None): + raise NotImplementedError() + + def remove_property(self, artifact_id, dependency_id, position=None, + type_name=None, type_version=None): + raise NotImplementedError() + + def artifact_export(self, artifact_id, + type_name=None, type_version=None): + raise NotImplementedError() + + def artifact_import(self, data, type_name=None, type_version=None): + raise NotImplementedError() diff --git a/glanceclient/v3/client.py b/glanceclient/v3/client.py new file mode 100644 index 0000000..f7c88b6 --- /dev/null +++ b/glanceclient/v3/client.py @@ -0,0 +1,41 @@ +# Copyright (c) 2015 Mirantis, Inc. +# +# 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 glanceclient.common import http +from glanceclient.common import utils +from glanceclient.v3 import artifacts + + +class Client(object): + """Client for the OpenStack Glance v3 API. + + :param string endpoint: A user-supplied endpoint URL for the glance + service. + :param string token: Token for authentication. + :param integer timeout: Allows customization of the timeout for client + http requests. (optional) + """ + + def __init__(self, endpoint, type_name, type_version, **kwargs): + endpoint, version = utils.strip_version(endpoint) + self.version = version or 3.0 + self.http_client = http.HTTPClient(endpoint, **kwargs) + + self.type_name = type_name + self.type_version = type_version + + self.artifacts = artifacts.Controller(self.http_client, + self.type_name, + self.type_version) |