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 |
|
| 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
|
Create an environment from an environment template
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
|
|
||||||
|
@ -139,6 +139,10 @@ class API(wsgi.Router):
|
|||||||
controller=applications_resource,
|
controller=applications_resource,
|
||||||
action='post',
|
action='post',
|
||||||
conditions={'method': ['POST']}, path='')
|
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:.*?}',
|
mapper.connect('/templates/{env_template_id}/services/{path:.*?}',
|
||||||
controller=applications_resource,
|
controller=applications_resource,
|
||||||
action='delete',
|
action='delete',
|
||||||
|
@ -21,6 +21,7 @@ from webob import exc
|
|||||||
from murano.api.v1 import request_statistics
|
from murano.api.v1 import request_statistics
|
||||||
from murano.common.helpers import token_sanitizer
|
from murano.common.helpers import token_sanitizer
|
||||||
from murano.common.i18n import _
|
from murano.common.i18n import _
|
||||||
|
from murano.common import policy
|
||||||
from murano.common import wsgi
|
from murano.common import wsgi
|
||||||
from murano.db.services import core_services
|
from murano.db.services import core_services
|
||||||
from murano import utils
|
from murano import utils
|
||||||
@ -144,16 +145,16 @@ class Controller(object):
|
|||||||
:param body: the information about the service
|
:param body: the information about the service
|
||||||
:return: the service description updated.
|
:return: the service description updated.
|
||||||
"""
|
"""
|
||||||
|
policy.check('update_service_env_template', request.context)
|
||||||
LOG.debug('Applications:Put <EnvTempId: {templ_id}, Path: {path}, '
|
LOG.debug('Applications:Put <EnvTempId: {templ_id}, Path: {path}, '
|
||||||
'Body: {body}>'.format(templ_id=env_template_id,
|
'Body: {body}>'.format(templ_id=env_template_id,
|
||||||
body=body,
|
body=body,
|
||||||
path=path))
|
path=path))
|
||||||
|
|
||||||
put_data = core_services.CoreServices.put_data
|
put_data = core_services.CoreServices.put_application_data
|
||||||
session_id = request.context.session
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = put_data(env_template_id, session_id, body, path)
|
result = put_data(env_template_id, body, path)
|
||||||
except (KeyError, ValueError):
|
except (KeyError, ValueError):
|
||||||
msg = _('The template does not exist {templ_id}').format(
|
msg = _('The template does not exist {templ_id}').format(
|
||||||
templ_id=env_template_id)
|
templ_id=env_template_id)
|
||||||
|
@ -91,7 +91,10 @@ class TraverseHelper(object):
|
|||||||
parent_path = '/'.join(path.split('/')[:-1])
|
parent_path = '/'.join(path.split('/')[:-1])
|
||||||
node = TraverseHelper.get(parent_path, source)
|
node = TraverseHelper.get(parent_path, source)
|
||||||
key = path[1:].split('/')[-1]
|
key = path[1:].split('/')[-1]
|
||||||
node[key] = value
|
if is_number(key):
|
||||||
|
node[int(key)] = value
|
||||||
|
else:
|
||||||
|
node[key] = value
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def insert(path, value, source):
|
def insert(path, value, source):
|
||||||
@ -139,6 +142,70 @@ class TraverseHelper(object):
|
|||||||
raise ValueError(_('Source object or path is malformed'))
|
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(value):
|
||||||
def build_entity_map_recursive(value, id_map):
|
def build_entity_map_recursive(value, id_map):
|
||||||
if isinstance(value, dict):
|
if isinstance(value, dict):
|
||||||
|
@ -229,3 +229,36 @@ class CoreServices(object):
|
|||||||
utils.TraverseHelper.remove(path, tmp_description)
|
utils.TraverseHelper.remove(path, tmp_description)
|
||||||
save_description(tmp_description, env_template_id)
|
save_description(tmp_description, env_template_id)
|
||||||
return tmp_description
|
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[4], body_returned['session_id'])
|
||||||
self.assertEqual(self.uuids[3], body_returned['environment_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):
|
def test_mallformed_env_body(self):
|
||||||
"""Check that an illegal temp name results in an HTTPClientError."""
|
"""Check that an illegal temp name results in an HTTPClientError."""
|
||||||
self._set_policy_rules(
|
self._set_policy_rules(
|
||||||
{'create_env_template': '@',
|
{'create_env_template': '@',
|
||||||
'create_environment': '@'}
|
'create_environment': '@'}
|
||||||
)
|
)
|
||||||
self. _create_env_template_no_service()
|
self._create_env_template_no_service()
|
||||||
|
|
||||||
self.expect_policy_check('create_environment',
|
self.expect_policy_check('create_environment',
|
||||||
{'env_template_id': self.uuids[0]})
|
{'env_template_id': self.uuids[0]})
|
||||||
@ -770,11 +792,12 @@ class TestEnvTemplateApi(tb.ControllerTest, tb.MuranoApiTestCase):
|
|||||||
"port": "8080",
|
"port": "8080",
|
||||||
"?": {
|
"?": {
|
||||||
"type": "io.murano.apps.apache.Tomcat",
|
"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 = 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)
|
self.expected_success(200, resp.status)
|
||||||
return json.loads(body)
|
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):
|
def delete_service_from_env_template(self, env_template_name, service_id):
|
||||||
uri = 'v1/templates/{0}/services/{1}'.format(env_template_name,
|
uri = 'v1/templates/{0}/services/{1}'.format(env_template_name,
|
||||||
service_id)
|
service_id)
|
||||||
|
@ -98,6 +98,22 @@ class TestEnvironmentTemplates(base.BaseApplicationCatalogTest):
|
|||||||
get_services_list_in_env_template(self.env_template['id'])
|
get_services_list_in_env_template(self.env_template['id'])
|
||||||
self.assertNotIn(service, services)
|
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')
|
@testtools.testcase.attr('smoke')
|
||||||
def test_create_public_env_template(self):
|
def test_create_public_env_template(self):
|
||||||
name = utils.generate_name('create_public_env_template')
|
name = utils.generate_name('create_public_env_template')
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Add application template update endpoint
|
Loading…
x
Reference in New Issue
Block a user