From 97070e10c45a168e294466fb8bea814940b07e84 Mon Sep 17 00:00:00 2001 From: tengqm Date: Wed, 5 Aug 2015 22:53:42 -0400 Subject: [PATCH] Support to Profile resource for cluster service This patch adds support to the 'Profile' resources from the cluster service (senlin). Change-Id: Ia62ca58d46db68fd4e8b35fb4c525e330f40ed33 --- openstack/cluster/v1/_proxy.py | 93 +++++++++++++++++++ openstack/cluster/v1/profile.py | 49 ++++++++++ .../tests/unit/cluster/v1/test_profile.py | 65 +++++++++++++ openstack/tests/unit/cluster/v1/test_proxy.py | 26 ++++++ 4 files changed, 233 insertions(+) create mode 100644 openstack/cluster/v1/profile.py create mode 100644 openstack/tests/unit/cluster/v1/test_profile.py diff --git a/openstack/cluster/v1/_proxy.py b/openstack/cluster/v1/_proxy.py index 15eb99ac..0c6cbee7 100644 --- a/openstack/cluster/v1/_proxy.py +++ b/openstack/cluster/v1/_proxy.py @@ -14,11 +14,103 @@ from openstack.cluster.v1 import action from openstack.cluster.v1 import cluster from openstack.cluster.v1 import node from openstack.cluster.v1 import policy +from openstack.cluster.v1 import profile from openstack import proxy class Proxy(proxy.BaseProxy): + def create_profile(self, **attrs): + """Create a new profile from attributes. + + :param dict attrs: Keyword arguments that will be used to create a + :class:`~openstack.cluster.v1.profile.Profile`, it is comprised + of the properties on the Profile class. + + :returns: The results of profile creation. + :rtype: :class:`~openstack.cluster.v1.profile.Profile`. + """ + return self._create(profile.Profile, **attrs) + + def delete_profile(self, value, ignore_missing=True): + """Delete a profile. + + :param value: The value can be either the name or ID of a profile or a + :class:`~openstack.cluster.v1.profile.Profile` instance. + :param bool ignore_missing: When set to ``False``, an exception + :class:`~openstack.exceptions.ResourceNotFound` will be raised when + the profile could not be found. When set to ``True``, no exception + will be raised when attempting to delete a non-existent profile. + + :returns: ``None`` + """ + self._delete(profile.Profile, value, ignore_missing=ignore_missing) + + def find_profile(self, value, ignore_missing=True): + """Find a single profile. + + :param value: The name or ID of a profile. + :param bool ignore_missing: When set to ``False`` + :class:`~openstack.exceptions.ResourceNotFound` will be + raised when the resource does not exist. + When set to ``True``, None will be returned when + attempting to find a nonexistent resource. + :returns: One :class:`~openstack.cluster.v1.profile.Profile` object + or None + """ + return profile.Profile.find(self.session, value, + ignore_missing=ignore_missing) + + def get_profile(self, value): + """Get a single profile. + + :param value: The value can be the name or ID of a profile or a + :class:`~openstack.cluster.v1.profile.Profile` instance. + + :returns: One :class:`~openstack.cluster.v1.profile.Profile` + :raises: :class:`~openstack.exceptions.ResourceNotFound` when no + profile matching the criteria could be found. + """ + return self._get(profile.Profile, value) + + def profiles(self, **query): + """Retrieve a generator of profiles. + + :param kwargs \*\*query: Optional query parameters to be sent to + restrict the profiles to be returned. Available parameters include: + + * show_deleted: A boolean value indicating whether soft-deleted + profiles should be returned as well. + * filters: A list of key-value pairs for Senlin server to determine + whether a profile should be included in the list result. + * sort_keys: A list of key names for sorting the resulted list. + * sort_dir: Direction for sorting, and its valid values are 'asc' + and 'desc'. + * limit: Requests a specified size of returned items from the + query. Returns a number of items up to the specified limit + value. + * marker: Specifies the ID of the last-seen item. Use the limit + parameter to make an initial limited request and use the ID of + the last-seen item from the response as the marker parameter + value in a subsequent limited request. + + :returns: A generator of profile instances. + """ + return self._list(profile.Profile, paginated=True, **query) + + def update_profile(self, value, **attrs): + """Update a profile. + + :param value: Either the name or the ID of the profile, or an instance + of :class:`~openstack.cluster.v1.profile.Profile`. + :param attrs: The attributes to update on the profile represented by + the ``value`` parameter. + + :returns: The updated profile. + :rtype: :class:`~openstack.cluster.v1.profile.Profile` + """ + return self._update(profile.Profile, value, **attrs) + def create_cluster(self, **attrs): """Create a new cluster from attributes. @@ -306,6 +398,7 @@ class Proxy(proxy.BaseProxy): actions should be returned as well. * sort_keys: A list of key names for sorting the resulted list. * sort_dir: Direction for sorting, and its valid values are 'asc' + and 'desc'. * limit: Requests a specified size of returned items from the query. Returns a number of items up to the specified limit value. diff --git a/openstack/cluster/v1/profile.py b/openstack/cluster/v1/profile.py new file mode 100644 index 00000000..ba9632a3 --- /dev/null +++ b/openstack/cluster/v1/profile.py @@ -0,0 +1,49 @@ +# 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 openstack.cluster import cluster_service +from openstack import resource + + +class Profile(resource.Resource): + resource_key = 'profile' + resources_key = 'profiles' + base_path = '/profiles' + service = cluster_service.ClusterService() + + # capabilities + allow_create = True + allow_retrieve = True + allow_update = True + allow_delete = True + allow_list = True + + patch_update = True + + # properties + #: The name of the profile + name = resource.prop('name') + #: The type of the profile. + type_name = resource.prop('type') + #: The permission string of the profile. + permission = resource.prop('permission') + #: The spec of the profile. + spec = resource.prop('spec', type=dict) + #: A collection of key-value pairs that are attached to the profile. + metadata = resource.prop('metadata', type=dict) + #: Timestamp of when the profile was created. + created_at = resource.prop('created_time') + #: Timestamp of when the profile was last updated. + updated_at = resource.prop('updated_time') + #: Timestamp of when the profile was deleted. This is only used on + #: profiles that were soft-deleted. + deleted_at = resource.prop('deleted_time') diff --git a/openstack/tests/unit/cluster/v1/test_profile.py b/openstack/tests/unit/cluster/v1/test_profile.py new file mode 100644 index 00000000..8dabeb7e --- /dev/null +++ b/openstack/tests/unit/cluster/v1/test_profile.py @@ -0,0 +1,65 @@ +# 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 openstack.cluster.v1 import profile + + +FAKE_ID = '9b127538-a675-4271-ab9b-f24f54cfe173' +FAKE_NAME = 'test_profile' + +FAKE = { + 'metadata': {}, + 'name': FAKE_NAME, + 'id': FAKE_ID, + 'permission': '', + 'spec': { + 'type': 'os.nova.server', + 'version': 1.0, + 'properties': { + 'flavor': 1, + 'image': 'cirros-0.3.2-x86_64-uec', + 'key_name': 'oskey', + 'name': 'cirros_server' + } + }, + 'type': 'os.nova.server' +} + + +class TestProfile(testtools.TestCase): + + def setUp(self): + super(TestProfile, self).setUp() + + def test_basic(self): + sot = profile.Profile() + self.assertEqual('profile', sot.resource_key) + self.assertEqual('profiles', sot.resources_key) + self.assertEqual('/profiles', sot.base_path) + self.assertEqual('clustering', sot.service.service_type) + self.assertTrue(sot.allow_create) + self.assertTrue(sot.allow_retrieve) + self.assertTrue(sot.allow_update) + self.assertTrue(sot.allow_delete) + self.assertTrue(sot.allow_list) + self.assertTrue(sot.patch_update) + + def test_instantiate(self): + sot = profile.Profile(FAKE) + self.assertEqual(FAKE['id'], sot.id) + self.assertEqual(FAKE['name'], sot.name) + self.assertEqual(FAKE['metadata'], sot.metadata) + self.assertEqual(FAKE['permission'], sot.permission) + self.assertEqual(FAKE['spec'], sot.spec) + self.assertEqual(FAKE['type'], sot.type_name) diff --git a/openstack/tests/unit/cluster/v1/test_proxy.py b/openstack/tests/unit/cluster/v1/test_proxy.py index 05d64b03..3172fb86 100644 --- a/openstack/tests/unit/cluster/v1/test_proxy.py +++ b/openstack/tests/unit/cluster/v1/test_proxy.py @@ -15,6 +15,7 @@ from openstack.cluster.v1 import action from openstack.cluster.v1 import cluster from openstack.cluster.v1 import node from openstack.cluster.v1 import policy +from openstack.cluster.v1 import profile from openstack.tests.unit import test_proxy_base @@ -23,6 +24,31 @@ class TestClusterProxy(test_proxy_base.TestProxyBase): super(TestClusterProxy, self).setUp() self.proxy = _proxy.Proxy(self.session) + def test_profile_create(self): + self.verify_create(self.proxy.create_profile, profile.Profile) + + def test_profile_delete(self): + self.verify_delete(self.proxy.delete_profile, profile.Profile, False) + + def test_profile_delete_ignore(self): + self.verify_delete(self.proxy.delete_profile, profile.Profile, True) + + def test_profile_find(self): + self.verify_find('openstack.cluster.v1.profile.Profile.find', + self.proxy.find_profile) + + def test_profile_get(self): + self.verify_get(self.proxy.get_profile, profile.Profile) + + def test_profiles(self): + self.verify_list(self.proxy.profiles, profile.Profile, + paginated=True, + method_kwargs={'limit': 2}, + expected_kwargs={'limit': 2}) + + def test_profile_update(self): + self.verify_update(self.proxy.update_profile, profile.Profile) + def test_cluster_create(self): self.verify_create(self.proxy.create_cluster, cluster.Cluster)