diff --git a/doc/source/ext/gen_ref.py b/doc/source/ext/gen_ref.py index 97b9bfde..15ff8182 100644 --- a/doc/source/ext/gen_ref.py +++ b/doc/source/ext/gen_ref.py @@ -55,4 +55,5 @@ def gen_ref(ver, title, names): gen_ref("", "Client Reference", ["client", "exc"]) gen_ref("v1", "Version 1 API Reference", - ["stacks", "resources", "events", "actions"]) + ["stacks", "resources", "events", "actions", + "software_configs", "software_deployments"]) diff --git a/heatclient/tests/test_software_configs.py b/heatclient/tests/test_software_configs.py new file mode 100644 index 00000000..4313e7ba --- /dev/null +++ b/heatclient/tests/test_software_configs.py @@ -0,0 +1,93 @@ +# 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 +import testtools + +from heatclient.v1.software_configs import SoftwareConfig +from heatclient.v1.software_configs import SoftwareConfigManager + + +class SoftwareConfigTest(testtools.TestCase): + + def setUp(self): + super(SoftwareConfigTest, self).setUp() + config_id = 'bca6871d-86c0-4aff-b792-58a1f6947b57' + self.config = SoftwareConfig(mock.MagicMock(), info={'id': config_id}) + self.config_id = config_id + + def test_delete(self): + self.config.manager.delete.return_value = None + self.assertIsNone(self.config.delete()) + kwargs = self.config.manager.delete.call_args[1] + self.assertEqual(self.config_id, kwargs['config_id']) + + def test_data(self): + self.assertEqual( + "" % self.config_id, str(self.config)) + self.config.manager.data.return_value = None + self.config.data(name='config_mysql') + kwargs = self.config.manager.data.call_args[1] + self.assertEqual('config_mysql', kwargs['name']) + + +class SoftwareConfigManagerTest(testtools.TestCase): + + def setUp(self): + super(SoftwareConfigManagerTest, self).setUp() + self.manager = SoftwareConfigManager(mock.MagicMock()) + + def test_get(self): + config_id = 'bca6871d-86c0-4aff-b792-58a1f6947b57' + data = { + 'id': config_id, + 'name': 'config_mysql', + 'group': 'Heat::Shell', + 'config': '#!/bin/bash', + 'inputs': [], + 'ouputs': [], + 'options': []} + + self.manager.client.json_request.return_value = ( + {}, {'software_config': data}) + result = self.manager.get(config_id=config_id) + self.assertEqual(SoftwareConfig(self.manager, data), result) + call_args = self.manager.client.json_request.call_args + self.assertEqual( + ('GET', '/software_configs/%s' % config_id), *call_args) + + def test_create(self): + config_id = 'bca6871d-86c0-4aff-b792-58a1f6947b57' + body = { + 'name': 'config_mysql', + 'group': 'Heat::Shell', + 'config': '#!/bin/bash', + 'inputs': [], + 'ouputs': [], + 'options': []} + data = body.copy() + data['id'] = config_id + self.manager.client.json_request.return_value = ( + {}, {'software_config': data}) + result = self.manager.create(**body) + self.assertEqual(SoftwareConfig(self.manager, data), result) + args, kargs = self.manager.client.json_request.call_args + self.assertEqual('POST', args[0]) + self.assertEqual('/software_configs', args[1]) + self.assertEqual({'data': body}, kargs) + + def test_delete(self): + config_id = 'bca6871d-86c0-4aff-b792-58a1f6947b57' + self.manager.delete(config_id) + call_args = self.manager.client.delete.call_args + self.assertEqual( + ('/software_configs/%s' % config_id,), *call_args) diff --git a/heatclient/tests/test_software_deployments.py b/heatclient/tests/test_software_deployments.py new file mode 100644 index 00000000..76a06a42 --- /dev/null +++ b/heatclient/tests/test_software_deployments.py @@ -0,0 +1,145 @@ +# 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 +import testtools + +from heatclient.v1.software_deployments import SoftwareDeployment +from heatclient.v1.software_deployments import SoftwareDeploymentManager + + +class SoftwareDeploymentTest(testtools.TestCase): + + def setUp(self): + super(SoftwareDeploymentTest, self).setUp() + deployment_id = 'bca6871d-86c0-4aff-b792-58a1f6947b57' + self.deployment = SoftwareDeployment( + mock.MagicMock(), info={'id': deployment_id}) + self.deployment_id = deployment_id + + def test_delete(self): + self.deployment.manager.delete.return_value = None + self.assertIsNone(self.deployment.delete()) + kwargs = self.deployment.manager.delete.call_args[1] + self.assertEqual(self.deployment_id, kwargs['deployment_id']) + + def test_update(self): + self.assertEqual( + "" % self.deployment_id, + str(self.deployment)) + self.deployment.manager.update.return_value = None + config_id = 'd00ba4aa-db33-42e1-92f4-2a6469260107' + self.assertIsNone(self.deployment.update(config_id=config_id)) + kwargs = self.deployment.manager.update.call_args[1] + self.assertEqual(self.deployment_id, kwargs['deployment_id']) + self.assertEqual(config_id, kwargs['config_id']) + + +class SoftwareDeploymentManagerTest(testtools.TestCase): + + def setUp(self): + super(SoftwareDeploymentManagerTest, self).setUp() + self.manager = SoftwareDeploymentManager(mock.MagicMock()) + + def test_list(self): + server_id = 'fc01f89f-e151-4dc5-9c28-543c0d20ed6a' + self.manager.client.json_request.return_value = ( + {}, + {'software_deployments': []}) + result = self.manager.list(server_id=server_id) + self.assertEqual([], result) + call_args = self.manager.client.get.call_args + self.assertEqual( + ('/software_deployments?server_id=%s' % server_id,), + *call_args) + + def test_get(self): + deployment_id = 'bca6871d-86c0-4aff-b792-58a1f6947b57' + config_id = 'd00ba4aa-db33-42e1-92f4-2a6469260107' + server_id = 'fb322564-7927-473d-8aad-68ae7fbf2abf' + data = { + 'id': deployment_id, + 'server_id': server_id, + 'input_values': {}, + 'output_values': {}, + 'action': 'INIT', + 'status': 'COMPLETE', + 'status_reason': None, + 'signal_id': None, + 'config_id': config_id, + 'config': '#!/bin/bash', + 'name': 'config_mysql', + 'group': 'Heat::Shell', + 'inputs': [], + 'outputs': [], + 'options': []} + + self.manager.client.json_request.return_value = ( + {}, {'software_deployment': data}) + result = self.manager.get(deployment_id=deployment_id) + self.assertEqual(SoftwareDeployment(self.manager, data), result) + call_args = self.manager.client.json_request.call_args + self.assertEqual( + ('GET', '/software_deployments/%s' % deployment_id), *call_args) + + def test_create(self): + deployment_id = 'bca6871d-86c0-4aff-b792-58a1f6947b57' + config_id = 'd00ba4aa-db33-42e1-92f4-2a6469260107' + server_id = 'fb322564-7927-473d-8aad-68ae7fbf2abf' + body = { + 'server_id': server_id, + 'input_values': {}, + 'action': 'INIT', + 'status': 'COMPLETE', + 'status_reason': None, + 'signal_id': None, + 'config_id': config_id} + data = body.copy() + data['id'] = deployment_id + self.manager.client.json_request.return_value = ( + {}, {'software_deployment': data}) + result = self.manager.create(**body) + self.assertEqual(SoftwareDeployment(self.manager, data), result) + args, kwargs = self.manager.client.json_request.call_args + self.assertEqual('POST', args[0]) + self.assertEqual('/software_deployments', args[1]) + self.assertEqual({'data': body}, kwargs) + + def test_delete(self): + deployment_id = 'bca6871d-86c0-4aff-b792-58a1f6947b57' + self.manager.delete(deployment_id) + call_args = self.manager.client.delete.call_args + self.assertEqual( + ('/software_deployments/%s' % deployment_id,), *call_args) + + def test_update(self): + deployment_id = 'bca6871d-86c0-4aff-b792-58a1f6947b57' + config_id = 'd00ba4aa-db33-42e1-92f4-2a6469260107' + server_id = 'fb322564-7927-473d-8aad-68ae7fbf2abf' + body = { + 'server_id': server_id, + 'input_values': {}, + 'action': 'DEPLOYED', + 'status': 'COMPLETE', + 'status_reason': None, + 'signal_id': None, + 'config_id': config_id} + data = body.copy() + data['id'] = deployment_id + self.manager.client.json_request.return_value = ( + {}, {'software_deployment': data}) + result = self.manager.update(deployment_id, **body) + self.assertEqual(SoftwareDeployment(self.manager, data), result) + args, kwargs = self.manager.client.json_request.call_args + self.assertEqual('PUT', args[0]) + self.assertEqual('/software_deployments/%s' % deployment_id, args[1]) + self.assertEqual({'data': body}, kwargs) diff --git a/heatclient/v1/client.py b/heatclient/v1/client.py index 827a4fcc..2ce73023 100644 --- a/heatclient/v1/client.py +++ b/heatclient/v1/client.py @@ -19,6 +19,8 @@ from heatclient.v1 import build_info from heatclient.v1 import events from heatclient.v1 import resource_types from heatclient.v1 import resources +from heatclient.v1 import software_configs +from heatclient.v1 import software_deployments from heatclient.v1 import stacks @@ -42,3 +44,8 @@ class Client(object): self.events = events.EventManager(self.http_client) self.actions = actions.ActionManager(self.http_client) self.build_info = build_info.BuildInfoManager(self.http_client) + self.software_deployments = \ + software_deployments.SoftwareDeploymentManager( + self.http_client) + self.software_configs = software_configs.SoftwareConfigManager( + self.http_client) diff --git a/heatclient/v1/software_configs.py b/heatclient/v1/software_configs.py new file mode 100644 index 00000000..9fa77d3e --- /dev/null +++ b/heatclient/v1/software_configs.py @@ -0,0 +1,53 @@ +# 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 copy + +from heatclient.openstack.common.apiclient import base + + +class SoftwareConfig(base.Resource): + def __repr__(self): + return "" % self._info + + def delete(self): + return self.manager.delete(config_id=self.id) + + def data(self, **kwargs): + return self.manager.data(self, **kwargs) + + def to_dict(self): + return copy.deepcopy(self._info) + + +class SoftwareConfigManager(base.BaseManager): + resource_class = SoftwareConfig + + def get(self, config_id): + """Get the details for a specific software config. + + :param config_id: ID of the software config + """ + resp, body = self.client.json_request( + 'GET', '/software_configs/%s' % config_id) + + return SoftwareConfig(self, body['software_config']) + + def create(self, **kwargs): + """Create a software config.""" + resp, body = self.client.json_request('POST', '/software_configs', + data=kwargs) + + return SoftwareConfig(self, body['software_config']) + + def delete(self, config_id): + """Delete a software config.""" + self._delete("/software_configs/%s" % config_id) diff --git a/heatclient/v1/software_deployments.py b/heatclient/v1/software_deployments.py new file mode 100644 index 00000000..a58bba85 --- /dev/null +++ b/heatclient/v1/software_deployments.py @@ -0,0 +1,66 @@ +# 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 copy + +from heatclient.openstack.common.apiclient import base +from heatclient.openstack.common.py3kcompat import urlutils + + +class SoftwareDeployment(base.Resource): + def __repr__(self): + return "" % self._info + + def update(self, **fields): + self.manager.update(deployment_id=self.id, **fields) + + def delete(self): + return self.manager.delete(deployment_id=self.id) + + def to_dict(self): + return copy.deepcopy(self._info) + + +class SoftwareDeploymentManager(base.BaseManager): + resource_class = SoftwareDeployment + + def list(self, **kwargs): + """Get a list of software deployments. + :rtype: list of :class:`SoftwareDeployment` + """ + url = '/software_deployments?%s' % urlutils.urlencode(kwargs) + return self._list(url, "software_deployments") + + def get(self, deployment_id): + """Get the details for a specific software deployment. + + :param deployment_id: ID of the software deployment + """ + resp, body = self.client.json_request( + 'GET', '/software_deployments/%s' % deployment_id) + + return SoftwareDeployment(self, body['software_deployment']) + + def create(self, **kwargs): + """Create a software deployment.""" + resp, body = self.client.json_request( + 'POST', '/software_deployments', data=kwargs) + return SoftwareDeployment(self, body['software_deployment']) + + def update(self, deployment_id, **kwargs): + """Update a software deployment.""" + resp, body = self.client.json_request( + 'PUT', '/software_deployments/%s' % deployment_id, data=kwargs) + return SoftwareDeployment(self, body['software_deployment']) + + def delete(self, deployment_id): + """Delete a software deployment.""" + self._delete("/software_deployments/%s" % deployment_id)