From 74207ee5f4bb6dd4c66cdef71ea8978ac2e11f9b Mon Sep 17 00:00:00 2001 From: Nikolay Starodubtsev Date: Wed, 15 Jul 2015 08:18:02 +0000 Subject: [PATCH] Add support for more Cloud Foundry API calls In this patch was added bind and unbind API calls. Some functions for it successful usage is also here. partial-implement: bp cloudfoundry-api-support Change-Id: I1152e707ad7a9a0446dda7f8ac4f84489b7c128a --- murano/api/v1/cloudfoundry/cfapi.py | 47 +++++++++++++++++-- murano/api/v1/cloudfoundry/router.py | 13 +++++ .../unit/api/v1/cloudfoundry/test_cfapi.py | 22 +++++++++ 3 files changed, 78 insertions(+), 4 deletions(-) diff --git a/murano/api/v1/cloudfoundry/cfapi.py b/murano/api/v1/cloudfoundry/cfapi.py index 77492a8a..b1f809a2 100644 --- a/murano/api/v1/cloudfoundry/cfapi.py +++ b/murano/api/v1/cloudfoundry/cfapi.py @@ -19,6 +19,7 @@ import uuid import muranoclient.client as client from oslo_config import cfg from oslo_log import log as logging +import six from webob import exc from murano.api.v1.cloudfoundry import auth as keystone_auth @@ -85,6 +86,12 @@ class Controller(object): "type": package.fully_qualified_name, "id": id}} + def _get_service(self, env, service_id): + for service in env.services: + if service['?']['id'] == service_id: + return service + return None + def list(self, req): user, passwd, keystone = self._check_auth(req) # Once we get here we were authorized by keystone @@ -211,11 +218,43 @@ class Controller(object): m_cli.sessions.deploy(environment_id, session_id) return {} - def bind(self, req, instance_id, id): - pass + def bind(self, req, body, instance_id, app_id): + filtered = [u'?', u'instance'] + db_service = db_cf.get_service_for_instance(instance_id) + if not db_service: + return {} - def unbind(self, req, instance_id, id): - pass + service_id = db_service.service_id + environment_id = db_service.environment_id + tenant = db_service.tenant + user, passwd, keystone = self._check_auth(req, tenant) + # Once we get here we were authorized by keystone + token = keystone.auth_token + m_cli = muranoclient(token) + + session_id = create_session(m_cli, environment_id) + env = m_cli.environments.get(environment_id, session_id) + LOG.debug('Got environment %s' % env) + service = self._get_service(env, service_id) + LOG.debug('Got service %s' % service) + credentials = {} + for k, v in six.iteritems(service): + if k not in filtered: + credentials[k] = v + + return {'credentials': credentials} + + def unbind(self, req, instance_id, app_id): + """Unsupported functionality + + murano doesn't support this kind of functionality, so we just need + to create a stub where the call will come. We can't raise something + like NotImplementedError because we will have problems on Cloud Foundry + side. The best way now it to return empty dict which will be correct + answer for Cloud Foundry. + """ + + return {} def get_last_operation(self): """Not implemented functionality diff --git a/murano/api/v1/cloudfoundry/router.py b/murano/api/v1/cloudfoundry/router.py index 1eeeeaf9..27bfde52 100644 --- a/murano/api/v1/cloudfoundry/router.py +++ b/murano/api/v1/cloudfoundry/router.py @@ -37,6 +37,19 @@ class API(wsgi.Router): controller=services_resource, action='deprovision', conditions={'method': ['DELETE']}) + + mapper.connect(('/v2/service_instances/{instance_id}/service_bindings/' + '{app_id}'), + controller=services_resource, + action='bind', + conditions={'method': ['PUT']}) + + mapper.connect(('/v2/service_instances/{instance_id}/service_bindings/' + '{app_id}'), + controller=services_resource, + action='unbind', + conditions={'method': ['DELETE']}) + mapper.connect(('/v2/service_instances/{instance_id}/last_operation'), controller=services_resource, action='get_last_operation', diff --git a/murano/tests/unit/api/v1/cloudfoundry/test_cfapi.py b/murano/tests/unit/api/v1/cloudfoundry/test_cfapi.py index 4a6ed9d7..bd62abf8 100644 --- a/murano/tests/unit/api/v1/cloudfoundry/test_cfapi.py +++ b/murano/tests/unit/api/v1/cloudfoundry/test_cfapi.py @@ -127,3 +127,25 @@ class TestController(base.MuranoTestCase): resp = self.controller.deprovision(self.request, '555-555') self.assertEqual({}, resp) + + @mock.patch('murano.api.v1.cloudfoundry.cfapi.muranoclient') + @mock.patch('murano.db.services.cf_connections.get_service_for_instance') + @mock.patch('murano.api.v1.cloudfoundry.auth.authenticate') + def test_bind(self, mock_auth, mock_get_si, mock_client): + service = mock.MagicMock() + service.service_id = '111-111' + service.tenant_id = '222-222' + service.env_id = '333-333' + mock_get_si.return_value = service + + services = [{'id': 'xxx-xxx-xxx', + '?': {'id': '111-111'}, + 'instance': {}, + 'smthg': 'nothing'}] + mock_client.return_value.environments.get =\ + mock.MagicMock(return_value=mock.MagicMock(services=services)) + + nice_resp = {'credentials': {'smthg': 'nothing', 'id': 'xxx-xxx-xxx'}} + resp = self.controller.bind(self.request, {}, '555-555', '666-666') + + self.assertEqual(nice_resp, resp)