Fix application template update
Updating an application/service in a environment template does not work and return 404 error. This patchs solves that bug. Change-Id: I03f51c45512c4282ef99ddc1ed9ba55460827a94 Closes-Bug: #1587833
This commit is contained in:
parent
9c7187fb02
commit
6e35fb4b57
@ -414,6 +414,86 @@ Get applications information from an environment template
|
||||
| 404 | The environment template does not exist |
|
||||
+----------------+-----------------------------------------------------------+
|
||||
|
||||
Update applications information from an environment template
|
||||
------------------------------------------------------------
|
||||
|
||||
*Request*
|
||||
|
||||
+----------+-----------------------------------------------+-----------------------------------+
|
||||
| Method | URI | Description |
|
||||
+==========+===============================================+===================================+
|
||||
| PUT | /templates/{env-temp-id}/services/{service-id}| It updates the service description|
|
||||
+----------+-----------------------------------------------+-----------------------------------+
|
||||
|
||||
*Parameters:*
|
||||
|
||||
* `env-temp-id` - The environment template ID, required
|
||||
* `service-id` - The service ID to be updated
|
||||
* payload - the service description
|
||||
|
||||
*Content-Type*
|
||||
application/json
|
||||
|
||||
*Example*
|
||||
|
||||
::
|
||||
|
||||
{
|
||||
"instance": {
|
||||
"assignFloatingIp": "true",
|
||||
"keyname": "mykeyname",
|
||||
"image": "cloud-fedora-v3",
|
||||
"flavor": "m1.medium",
|
||||
"?": {
|
||||
"type": "io.murano.resources.LinuxMuranoInstance",
|
||||
"id": "ef984a74-29a4-45c0-b1dc-2ab9f075732e"
|
||||
}
|
||||
},
|
||||
"name": "orion",
|
||||
"port": "8080",
|
||||
"?": {
|
||||
"type": "io.murano.apps.apache.Tomcat",
|
||||
"id": "54cea43d-5970-4c73-b9ac-fea656f3c722"
|
||||
}
|
||||
}
|
||||
|
||||
*Response*
|
||||
|
||||
::
|
||||
|
||||
|
||||
{
|
||||
"instance":
|
||||
{
|
||||
"assignFloatingIp": "true",
|
||||
"keyname": "mykeyname",
|
||||
"image": "cloud-fedora-v3",
|
||||
"flavor": "m1.medium",
|
||||
"?":
|
||||
{
|
||||
"type": "io.murano.resources.LinuxMuranoInstance",
|
||||
"id": "ef984a74-29a4-45c0-b1dc-2ab9f075732e"
|
||||
}
|
||||
},
|
||||
"name": "orion",
|
||||
"?":
|
||||
{
|
||||
"type": "io.murano.apps.apache.Tomcat",
|
||||
"id": "54cea43d-5970-4c73-b9ac-fea656f3c722"
|
||||
},
|
||||
"port": "8080"
|
||||
}
|
||||
|
||||
+----------------+-----------------------------------------------------------+
|
||||
| Code | Description |
|
||||
+================+===========================================================+
|
||||
| 200 | OK. Environment Template updated successfully |
|
||||
+----------------+-----------------------------------------------------------+
|
||||
| 401 | User is not authorized to access this session |
|
||||
+----------------+-----------------------------------------------------------+
|
||||
| 404 | The environment template does not exist |
|
||||
+----------------+-----------------------------------------------------------+
|
||||
|
||||
Create an environment from an environment template
|
||||
--------------------------------------------------
|
||||
|
||||
|
@ -139,6 +139,10 @@ class API(wsgi.Router):
|
||||
controller=applications_resource,
|
||||
action='post',
|
||||
conditions={'method': ['POST']}, path='')
|
||||
mapper.connect('/templates/{env_template_id}/services/{path:.*?}',
|
||||
controller=applications_resource,
|
||||
action='put',
|
||||
conditions={'method': ['PUT']}, path='')
|
||||
mapper.connect('/templates/{env_template_id}/services/{path:.*?}',
|
||||
controller=applications_resource,
|
||||
action='delete',
|
||||
|
@ -21,6 +21,7 @@ from webob import exc
|
||||
from murano.api.v1 import request_statistics
|
||||
from murano.common.helpers import token_sanitizer
|
||||
from murano.common.i18n import _
|
||||
from murano.common import policy
|
||||
from murano.common import wsgi
|
||||
from murano.db.services import core_services
|
||||
from murano import utils
|
||||
@ -144,16 +145,16 @@ class Controller(object):
|
||||
:param body: the information about the service
|
||||
:return: the service description updated.
|
||||
"""
|
||||
policy.check('update_service_env_template', request.context)
|
||||
LOG.debug('Applications:Put <EnvTempId: {templ_id}, Path: {path}, '
|
||||
'Body: {body}>'.format(templ_id=env_template_id,
|
||||
body=body,
|
||||
path=path))
|
||||
|
||||
put_data = core_services.CoreServices.put_data
|
||||
session_id = request.context.session
|
||||
put_data = core_services.CoreServices.put_application_data
|
||||
|
||||
try:
|
||||
result = put_data(env_template_id, session_id, body, path)
|
||||
result = put_data(env_template_id, body, path)
|
||||
except (KeyError, ValueError):
|
||||
msg = _('The template does not exist {templ_id}').format(
|
||||
templ_id=env_template_id)
|
||||
|
@ -91,7 +91,10 @@ class TraverseHelper(object):
|
||||
parent_path = '/'.join(path.split('/')[:-1])
|
||||
node = TraverseHelper.get(parent_path, source)
|
||||
key = path[1:].split('/')[-1]
|
||||
node[key] = value
|
||||
if is_number(key):
|
||||
node[int(key)] = value
|
||||
else:
|
||||
node[key] = value
|
||||
|
||||
@staticmethod
|
||||
def insert(path, value, source):
|
||||
@ -139,6 +142,70 @@ class TraverseHelper(object):
|
||||
raise ValueError(_('Source object or path is malformed'))
|
||||
|
||||
|
||||
def is_number(var):
|
||||
try:
|
||||
int(var)
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def is_different(obj1, obj2):
|
||||
"""Stripped-down version of deep.diff comparator
|
||||
|
||||
Compares arbitrary nested objects, handles circular links, but doesn't
|
||||
point to the first difference as deep.diff does.
|
||||
"""
|
||||
class Difference(Exception):
|
||||
pass
|
||||
|
||||
def is_in(o, st):
|
||||
for _o in st:
|
||||
if o is _o:
|
||||
return True
|
||||
return False
|
||||
|
||||
def rec(o1, o2, stack1=(), stack2=()):
|
||||
if is_in(o1, stack1) and is_in(o2, stack2):
|
||||
# circular reference detected - break the loop
|
||||
return
|
||||
elif is_in(o1, stack1):
|
||||
raise Difference()
|
||||
else:
|
||||
stack1 += (o1,)
|
||||
stack2 += (o2,)
|
||||
|
||||
if o1 is o2:
|
||||
return
|
||||
elif (isinstance(o1, six.string_types) and
|
||||
isinstance(o2, six.string_types)) and o1 == o2:
|
||||
return
|
||||
elif type(o1) != type(o2):
|
||||
raise Difference()
|
||||
elif isinstance(o1, dict):
|
||||
# check for keys inequality
|
||||
rec(o1.keys(), o2.keys(), stack1, stack2)
|
||||
for key in o1.keys():
|
||||
rec(o1[key], o2[key], stack1, stack2)
|
||||
elif isinstance(o1, (list, tuple, set)):
|
||||
if len(o1) != len(o2):
|
||||
raise Difference()
|
||||
else:
|
||||
for _o1, _o2 in zip(o1, o2):
|
||||
rec(_o1, _o2, stack1, stack2)
|
||||
elif hasattr(o1, '__dict__'):
|
||||
return rec(o1.__dict__, o2.__dict__, stack1, stack2)
|
||||
elif o1 != o2:
|
||||
raise Difference()
|
||||
|
||||
try:
|
||||
rec(obj1, obj2)
|
||||
except Difference:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def build_entity_map(value):
|
||||
def build_entity_map_recursive(value, id_map):
|
||||
if isinstance(value, dict):
|
||||
|
@ -229,3 +229,36 @@ class CoreServices(object):
|
||||
utils.TraverseHelper.remove(path, tmp_description)
|
||||
save_description(tmp_description, env_template_id)
|
||||
return tmp_description
|
||||
|
||||
@staticmethod
|
||||
def put_application_data(env_template_id, data, path):
|
||||
"""It stores the application data inside the template description.
|
||||
|
||||
:param env_template_id: The env_template_id to obtain the data
|
||||
:param data: the template description
|
||||
:param path: Id of service for which we checking status.
|
||||
:return: The template description
|
||||
"""
|
||||
get_description = env_temp.EnvTemplateServices.get_description
|
||||
save_description = env_temp.EnvTemplateServices.save_description
|
||||
|
||||
temp_description = get_description(env_template_id)
|
||||
if temp_description is None:
|
||||
msg = _('Environment Template <EnvId {0}> is not found').format(
|
||||
env_template_id)
|
||||
LOG.error(msg)
|
||||
raise exc.HTTPNotFound(explanation=msg)
|
||||
|
||||
count = 0
|
||||
id = path[1:].split('/')[-1]
|
||||
for service in temp_description["services"]:
|
||||
if service["?"]["id"]:
|
||||
if service["?"]["id"] == id:
|
||||
break
|
||||
count+1
|
||||
|
||||
utils.TraverseHelper.update("services/{0}".format(count),
|
||||
data, temp_description)
|
||||
temp_description['updated'] = str(timeutils.utcnow())
|
||||
save_description(temp_description, env_template_id)
|
||||
return data
|
||||
|
@ -668,13 +668,35 @@ class TestEnvTemplateApi(tb.ControllerTest, tb.MuranoApiTestCase):
|
||||
self.assertEqual(self.uuids[4], body_returned['session_id'])
|
||||
self.assertEqual(self.uuids[3], body_returned['environment_id'])
|
||||
|
||||
def test_update_service_in_template(self):
|
||||
"""Test the service is updated in the environment template"""
|
||||
self.fixture = self.useFixture(config_fixture.Config())
|
||||
self.fixture.conf(args=[])
|
||||
self._set_policy_rules(
|
||||
{'create_env_template': '@',
|
||||
'update_service_env_template': '@'}
|
||||
)
|
||||
updated_env = "UPDATED_ENV"
|
||||
env_template = self._create_env_template_services()
|
||||
self.expect_policy_check('update_service_env_template')
|
||||
env_template["name"] = updated_env
|
||||
|
||||
req = self._put('/templates/{0}/services/{1}'.
|
||||
format(self.uuids[0], "service_id"),
|
||||
jsonutils.dump_as_bytes(env_template))
|
||||
result = req.get_response(self.api)
|
||||
self.assertIsNotNone(result)
|
||||
self.assertEqual(200, result.status_code)
|
||||
body_returned = jsonutils.loads(result.body)
|
||||
self.assertEqual(updated_env, body_returned['name'])
|
||||
|
||||
def test_mallformed_env_body(self):
|
||||
"""Check that an illegal temp name results in an HTTPClientError."""
|
||||
self._set_policy_rules(
|
||||
{'create_env_template': '@',
|
||||
'create_environment': '@'}
|
||||
)
|
||||
self. _create_env_template_no_service()
|
||||
self._create_env_template_no_service()
|
||||
|
||||
self.expect_policy_check('create_environment',
|
||||
{'env_template_id': self.uuids[0]})
|
||||
@ -770,11 +792,12 @@ class TestEnvTemplateApi(tb.ControllerTest, tb.MuranoApiTestCase):
|
||||
"port": "8080",
|
||||
"?": {
|
||||
"type": "io.murano.apps.apache.Tomcat",
|
||||
"id": "54cea43d-5970-4c73-b9ac-fea656f3c722"
|
||||
"id": "service_id"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
req = self._post('/templates', jsonutils.dump_as_bytes(body))
|
||||
req.get_response(self.api)
|
||||
result = req.get_response(self.api)
|
||||
return result.json
|
||||
|
@ -331,6 +331,14 @@ class ApplicationCatalogClient(rest_client.RestClient):
|
||||
self.expected_success(200, resp.status)
|
||||
return json.loads(body)
|
||||
|
||||
def update_service_from_env_template(self, env_template_id, service_id,
|
||||
post_body):
|
||||
uri = 'v1/templates/{0}/services/{1}'.format(env_template_id,
|
||||
service_id)
|
||||
resp, body = self.put(uri, json.dumps(post_body))
|
||||
self.expected_success(200, resp.status)
|
||||
return self._parse_resp(body)
|
||||
|
||||
def delete_service_from_env_template(self, env_template_name, service_id):
|
||||
uri = 'v1/templates/{0}/services/{1}'.format(env_template_name,
|
||||
service_id)
|
||||
|
@ -98,6 +98,22 @@ class TestEnvironmentTemplates(base.BaseApplicationCatalogTest):
|
||||
get_services_list_in_env_template(self.env_template['id'])
|
||||
self.assertNotIn(service, services)
|
||||
|
||||
@testtools.testcase.attr('smoke')
|
||||
def test_update_service_in_env_templates(self):
|
||||
env_template_services = self.application_catalog_client.\
|
||||
get_services_list_in_env_template(self.env_template['id'])
|
||||
self.assertIsInstance(env_template_services, list)
|
||||
post_body = self._get_demo_app()
|
||||
service = self.application_catalog_client.\
|
||||
create_service_in_env_template(self.env_template['id'], post_body)
|
||||
self.assertEqual(post_body['name'], service['name'])
|
||||
post_body["name"] = "updated_name"
|
||||
service = self.application_catalog_client.\
|
||||
update_service_from_env_template(self.env_template['id'],
|
||||
service["?"]["id"],
|
||||
post_body)
|
||||
self.assertEqual("updated_name", service['name'])
|
||||
|
||||
@testtools.testcase.attr('smoke')
|
||||
def test_create_public_env_template(self):
|
||||
name = utils.generate_name('create_public_env_template')
|
||||
|
@ -0,0 +1,3 @@
|
||||
---
|
||||
features:
|
||||
- Add application template update endpoint
|
Loading…
Reference in New Issue
Block a user