Use stevedore Extensions for TOSCA definitions

This changes the TOSCA Parser extensions implementation to use a
stevedore Extensions namespace (toscaparser.extensions) to allow
TOSCA schema extensions to be loaded from other sources without
requiring them to be included in the tosca-parser repository.

Change-Id: Ia4d9430c398b2911043047d843419ff6edebfe3f
This commit is contained in:
Bob.Haddleton 2018-05-30 21:43:42 -05:00 committed by Bob Haddleton
parent 009e5f29d6
commit de252f95fe
6 changed files with 38 additions and 39 deletions

View File

@ -16,3 +16,7 @@ entry point as::
tosca-parser --template-file=toscaparser/tests/data/tosca_helloworld.yaml
The value to the --template-file is required to be a relative or an absolute path.
Custom template versions can be created and supported outside of TOSCA Parser
using the toscaparser.extensions namespace. See the NFV and MEC extensions
for examples of how to define custom template definitions and versions.

View File

@ -7,4 +7,5 @@ cliff!=2.9.0,>=2.8.0 # Apache-2.0
PyYAML>=3.12 # MIT
python-dateutil>=2.5.3 # BSD
six>=1.10.0 # MIT
stevedore>=1.20.0 # Apache-2.0
requests>=2.14.2 # Apache-2.0

View File

@ -27,6 +27,9 @@ packages =
[entry_points]
console_scripts =
tosca-parser = toscaparser.shell:main
toscaparser.extensions =
tosca_simple_profile_for_nfv_1_0_0 = toscaparser.extensions.nfv.tosca_simple_profile_for_nfv_1_0_0:NfvProfile_1_0_0
tosca_simple_profile_for_mec_1_0_0 = toscaparser.extensions.mec.tosca_simple_profile_for_mec_1_0_0:MecProfile_1_0_0
[compile_catalog]
directory = toscaparser/locale

View File

@ -16,6 +16,8 @@ import importlib
import logging
import os
from stevedore import extension
from toscaparser.common.exception import ToscaExtAttributeError
from toscaparser.common.exception import ToscaExtImportError
@ -32,41 +34,26 @@ class ExtTools(object):
'''Dynamically load all the extensions .'''
extensions = collections.OrderedDict()
# Use the absolute path of the class path
abs_path = os.path.dirname(os.path.abspath(__file__))
extns = extension.ExtensionManager(namespace='toscaparser.extensions',
invoke_on_load=True).extensions
extdirs = [e for e in os.listdir(abs_path) if
not e.startswith('tests') and
os.path.isdir(os.path.join(abs_path, e))]
for e in extns:
try:
extinfo = importlib.import_module(e.plugin.__module__)
base_path = os.path.dirname(extinfo.__file__)
version = e.plugin().VERSION
defs_file = base_path + '/' + e.plugin().DEFS_FILE
for e in extdirs:
log.info(e)
extpath = abs_path + '/' + e
# Grab all the extension files in the given path
ext_files = [f for f in os.listdir(extpath) if f.endswith('.py')
and not f.startswith('__init__')]
# Sections is an optional attribute
sections = getattr(e.plugin(), 'SECTIONS', ())
# For each module, pick out the target translation class
for f in ext_files:
log.info(f)
ext_name = 'toscaparser/extensions/' + e + '/' + f.strip('.py')
ext_name = ext_name.replace('/', '.')
try:
extinfo = importlib.import_module(ext_name)
version = getattr(extinfo, 'VERSION')
defs_file = extpath + '/' + getattr(extinfo, 'DEFS_FILE')
# Sections is an optional attribute
sections = getattr(extinfo, 'SECTIONS', ())
extensions[version] = {'sections': sections,
'defs_file': defs_file}
except ImportError:
raise ToscaExtImportError(ext_name=ext_name)
except AttributeError:
attrs = ', '.join(REQUIRED_ATTRIBUTES)
raise ToscaExtAttributeError(ext_name=ext_name,
attrs=attrs)
extensions[version] = {'sections': sections,
'defs_file': defs_file}
except ImportError:
raise ToscaExtImportError(ext_name=e.name)
except AttributeError:
attrs = ', '.join(REQUIRED_ATTRIBUTES)
raise ToscaExtAttributeError(ext_name=e.name, attrs=attrs)
return extensions

View File

@ -12,8 +12,10 @@
# VERSION and DEFS_FILE are required for all extensions
VERSION = 'tosca_simple_profile_for_mec_1_0_0'
DEFS_FILE = "TOSCA_mec_definition_1_0_0.yaml"
class MecProfile_1_0_0(object):
VERSION = 'tosca_simple_profile_for_mec_1_0_0'
SECTIONS = ('metadata')
DEFS_FILE = "TOSCA_mec_definition_1_0_0.yaml"
SECTIONS = ('metadata')

View File

@ -9,11 +9,13 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# VERSION and DEFS_FILE are required for all extensions
VERSION = 'tosca_simple_profile_for_nfv_1_0_0'
DEFS_FILE = "TOSCA_nfv_definition_1_0_0.yaml"
class NfvProfile_1_0_0(object):
VERSION = 'tosca_simple_profile_for_nfv_1_0_0'
SECTIONS = ('metadata')
DEFS_FILE = 'TOSCA_nfv_definition_1_0_0.yaml'
SECTIONS = ('metadata')