summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Fedosin <mfedosin@mirantis.com>2015-06-09 22:14:03 +0300
committerMike Fedosin <mfedosin@mirantis.com>2015-08-26 20:02:10 +0300
commit5d847b92cdf62596dc0448adf85a797f82b51d0d (patch)
treec6736f1164e73dc962f78e4c9031bc966000d7df
parent24a7448c650fc302ccbb5d01e4a129d889f7cb0d (diff)
downloadpython-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__.py37
-rw-r--r--glanceclient/tests/unit/v3/test_artifact_type.py88
-rw-r--r--glanceclient/tests/unit/v3/test_artifacts.py28
-rw-r--r--glanceclient/v3/__init__.py59
-rw-r--r--glanceclient/v3/artifacts.py91
-rw-r--r--glanceclient/v3/client.py41
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)