'GetPackageUI' API can now be called even if Glare is used
Since Glare support was introduced the 'catalog/packages' part of Murano API (/v1/catalog/packages) became obsolete and was intended to be used for "legacy" (i.e. non-glare-based) package storage. The murano client was supposed to directly call glare to retrieve the packages. However, the "GetPackageUI" call (GET /v1/catalog/packages/%pkg_id%/ui) is different: not all the packages bundle the UI definitions, some require Murano to generate them based on the contents of the package. This is true for HOT-based packages and others, plugin-based ones. In future this will be true for 100% of the packages when the dynamic ui and object model generation is added. Because of this that API should be callable even if Glare is configured as a package storage backend. It should fetch the artifact from glare, unpack it and use whatever plugin-specific logic required to generate the UI definitions for this particular package. This patch introduces appropriate change while maintaining the backwards compatibility: in the legacy mode (i.e. when murano's DB acts as package storage) the UI is read directly from an appropriate DB table without fetching the whole package. This fixes the issue when the HOT-based packages could not be deplpoyed properly with murano-dashboard, but the murano-client has to be updated as well to properly call the modified API even if Glare is enabled. Change-Id: Id9327e4015e1c0a1553c0b1a0151a94ee4da2928 Partial-bug: #1565805
This commit is contained in:
parent
0b3778af7c
commit
2858689767
@ -14,6 +14,7 @@
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_middleware import request_id as oslo_request_id
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from murano.common.i18n import _
|
||||
from murano.common import wsgi
|
||||
@ -50,6 +51,9 @@ class ContextMiddleware(wsgi.Middleware):
|
||||
'request_id': req.environ.get(oslo_request_id.ENV_REQUEST_ID),
|
||||
'roles': roles
|
||||
}
|
||||
sc_header = req.headers.get('X-Service-Catalog')
|
||||
if sc_header:
|
||||
kwargs['service_catalog'] = jsonutils.loads(sc_header)
|
||||
req.context = murano.context.RequestContext(**kwargs)
|
||||
|
||||
@classmethod
|
||||
|
@ -18,6 +18,8 @@ import os
|
||||
import tempfile
|
||||
|
||||
import jsonschema
|
||||
from keystoneclient import exceptions as keystone_ex
|
||||
from keystoneclient import service_catalog
|
||||
from oslo_config import cfg
|
||||
from oslo_db import exception as db_exc
|
||||
from oslo_log import log as logging
|
||||
@ -34,6 +36,7 @@ from murano.db.catalog import api as db_api
|
||||
from murano.common.i18n import _, _LW
|
||||
from murano.packages import exceptions as pkg_exc
|
||||
from murano.packages import load_utils
|
||||
from muranoclient.glance import client as glare_client
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -266,11 +269,21 @@ class Controller(object):
|
||||
os.remove(tempf.name)
|
||||
|
||||
def get_ui(self, req, package_id):
|
||||
if CONF.engine.packages_service == 'murano':
|
||||
target = {'package_id': package_id}
|
||||
policy.check("get_package", req.context, target)
|
||||
|
||||
package = db_api.package_get(package_id, req.context)
|
||||
return package.ui_definition
|
||||
else:
|
||||
g_client = self._get_glare_client(req)
|
||||
blob_data = g_client.artifacts.download_blob(package_id, 'archive')
|
||||
with tempfile.NamedTemporaryFile() as tempf:
|
||||
for chunk in blob_data:
|
||||
tempf.write(chunk)
|
||||
with load_utils.load_from_file(tempf.name, target_dir=None,
|
||||
drop_dir=True) as pkg:
|
||||
return pkg.ui
|
||||
|
||||
def get_logo(self, req, package_id):
|
||||
target = {'package_id': package_id}
|
||||
@ -392,6 +405,38 @@ class Controller(object):
|
||||
raise exc.HTTPForbidden(explanation=msg)
|
||||
db_api.category_delete(category_id)
|
||||
|
||||
def _get_glare_client(self, request):
|
||||
glare_settings = CONF.glare
|
||||
token = request.context.auth_token
|
||||
url = glare_settings.url
|
||||
if not url:
|
||||
self._get_glare_url(request)
|
||||
client = glare_client.Client(
|
||||
endpoint=url, token=token, insecure=glare_settings.insecure,
|
||||
key_file=glare_settings.key_file or None,
|
||||
ca_file=glare_settings.ca_file or None,
|
||||
cert_file=glare_settings.cert_file or None,
|
||||
type_name='murano',
|
||||
type_version=1)
|
||||
return client
|
||||
|
||||
def _get_glare_url(self, request):
|
||||
sc = request.context.service_catalog
|
||||
token = request.context.auth_token
|
||||
try:
|
||||
return service_catalog.ServiceCatalogV2(
|
||||
{'serviceCatalog': sc}).url_for(
|
||||
service_type='artifact',
|
||||
endpoint_type=CONF.glare.endpoint_type,
|
||||
region_name=CONF.home_region)
|
||||
except keystone_ex.EndpointNotFound:
|
||||
return service_catalog.ServiceCatalogV3(
|
||||
token,
|
||||
{'catalog': sc}).url_for(
|
||||
service_type='artifact',
|
||||
endpoint_type=CONF.glare.endpoint_type,
|
||||
region_name=CONF.home_region)
|
||||
|
||||
|
||||
def create_resource():
|
||||
specific_content_types = {
|
||||
|
@ -25,11 +25,12 @@ class RequestContext(context.RequestContext):
|
||||
"""
|
||||
|
||||
def __init__(self, session=None,
|
||||
roles=None, is_admin=None,
|
||||
roles=None, is_admin=None, service_catalog=None,
|
||||
**kwargs):
|
||||
super(RequestContext, self).__init__(**kwargs)
|
||||
self.session = session
|
||||
|
||||
self.roles = roles or []
|
||||
self.service_catalog = service_catalog
|
||||
self.is_admin = is_admin
|
||||
if self.is_admin is None:
|
||||
self.is_admin = policy.check_is_admin(self)
|
||||
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
fixes:
|
||||
- Fixed a bug when the UI dialog was not displayed in Murano Dashboard for
|
||||
applications which don't have UI definitions bundled in the package but
|
||||
generate them based on the package contents instead. This usually affected
|
||||
HOT-based packages and other non-muranopl-based applications.
|
Loading…
Reference in New Issue
Block a user