diff options
Diffstat (limited to 'vnfsdk_pkgtools/packager/toscameta.py')
-rw-r--r-- | vnfsdk_pkgtools/packager/toscameta.py | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/vnfsdk_pkgtools/packager/toscameta.py b/vnfsdk_pkgtools/packager/toscameta.py new file mode 100644 index 0000000..fc51f3c --- /dev/null +++ b/vnfsdk_pkgtools/packager/toscameta.py @@ -0,0 +1,222 @@ +# Copyright (c) 2019 Intel Corp. All rights reserved. +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging +import os +import pprint + +from ruamel import yaml # @UnresolvedImport +import six + +from vnfsdk_pkgtools.packager import utils + +LOG = logging.getLogger(__name__) + +META_FILE = 'TOSCA-Metadata/TOSCA.meta' + +META_FILE_VERSION_KEY = 'TOSCA-Meta-File-Version' +META_FILE_VERSION_VALUE = '1.0' +META_CSAR_VERSION_KEY = 'CSAR-Version' +META_CSAR_VERSION_VALUE = '1.1' +META_CREATED_BY_KEY = 'Created-By' +META_CREATED_BY_VALUE = 'ONAP VNFSDK pkgtools' + +META_ENTRY_DEFINITIONS_KEY = 'Entry-Definitions' + +BASE_META = { + META_FILE_VERSION_KEY: META_FILE_VERSION_VALUE, + META_CSAR_VERSION_KEY: META_CSAR_VERSION_VALUE, +} + + +class ToscaMeta(object): + META_ENTRY_MANIFEST_FILE_KEY = 'ETSI-Entry-Manifest' + META_ENTRY_HISTORY_FILE_KEY = 'ETSI-Entry-Change-Log' + META_ENTRY_TESTS_DIR_KEY = 'ETSI-Entry-Tests' + META_ENTRY_LICENSES_DIR_KEY = 'ETSI-Entry-Licenses' + META_ENTRY_CERT_FILE_KEY = 'ETSI-Entry-Certificate' + REQUIRED_KEYS = [ META_FILE_VERSION_KEY, META_CSAR_VERSION_KEY, + META_CREATED_BY_KEY, META_ENTRY_DEFINITIONS_KEY, + META_ENTRY_MANIFEST_FILE_KEY, META_ENTRY_HISTORY_FILE_KEY, + META_ENTRY_LICENSES_DIR_KEY, + ] + OPTIONAL_KEYS = [META_ENTRY_TESTS_DIR_KEY, META_ENTRY_CERT_FILE_KEY] + + def __init__(self, base_dir, entry, manifest=None, changelog=None, + licenses=None, tests=None, certificate=None, + meta_file_version=META_FILE_VERSION_VALUE, + meta_csar_version=META_CSAR_VERSION_VALUE, + meta_created_by=META_CREATED_BY_VALUE): + + self.base_dir = base_dir + + metadata = {} + metadata[META_FILE_VERSION_KEY] = str(meta_file_version) + metadata[META_CSAR_VERSION_KEY] = str(meta_csar_version) + metadata[META_CREATED_BY_KEY] = meta_created_by + metadata[META_ENTRY_DEFINITIONS_KEY] = entry + if manifest: + metadata[self.META_ENTRY_MANIFEST_FILE_KEY] = manifest + if changelog: + metadata[self.META_ENTRY_HISTORY_FILE_KEY] = changelog + if licenses: + metadata[self.META_ENTRY_LICENSES_DIR_KEY] = licenses + if tests: + metadata[self.META_ENTRY_TESTS_DIR_KEY] = tests + if certificate: + metadata[self.META_ENTRY_CERT_FILE_KEY] = certificate + + self.metadata = self._validate(metadata) + + def _validate(self, metadata): + for (key, value) in six.iteritems(BASE_META): + if metadata.get(key) != value: + raise ValueError('TOSCA.meta: {} must be {}'.format(key, value)) + + utils.check_file_dir(root=self.base_dir, + entry=metadata.get(META_ENTRY_DEFINITIONS_KEY), + msg='Please specify a valid entry point.', + check_dir=False) + entry_file = os.path.join(self.base_dir, + metadata.get(META_ENTRY_DEFINITIONS_KEY)) + try: + with open(entry_file) as f: + v = yaml.safe_load(f)['tosca_definitions_version'] + except: + raise ValueError('Entry file {} is not a valid tosca simple yaml file'.format(entry_file)) + + if metadata.get(self.META_ENTRY_MANIFEST_FILE_KEY): + utils.check_file_dir(root=self.base_dir, + entry=metadata[self.META_ENTRY_MANIFEST_FILE_KEY], + msg='Please specify a valid manifest file.', + check_dir=False) + if metadata.get(self.META_ENTRY_HISTORY_FILE_KEY): + utils.check_file_dir(root=self.base_dir, + entry=metadata[self.META_ENTRY_HISTORY_FILE_KEY], + msg='Please specify a valid change history file.', + check_dir=False) + if metadata.get(self.META_ENTRY_LICENSES_DIR_KEY): + utils.check_file_dir(root=self.base_dir, + entry=metadata[self.META_ENTRY_LICENSES_DIR_KEY], + msg='Please specify a valid license directory.', + check_dir=True) + if metadata.get(self.META_ENTRY_TESTS_DIR_KEY): + utils.check_file_dir(root=self.base_dir, + entry=metadata[self.META_ENTRY_TESTS_DIR_KEY], + msg='Please specify a valid test directory.', + check_dir=True) + if metadata.get(self.META_ENTRY_CERT_FILE_KEY): + utils.check_file_dir(root=self.base_dir, + entry=metadata[self.META_ENTRY_CERT_FILE_KEY], + msg='Please specify a valid certificate file.', + check_dir=False) + missing_keys = [key for key in self.REQUIRED_KEYS if key not in metadata] + if missing_keys: + raise ValueError('TOSCA.meta: missing keys: {}'.format(','.join(missing_keys))) + return metadata + + def dump_as_string(self): + s = "" + for key in self.REQUIRED_KEYS + self.OPTIONAL_KEYS: + if self.metadata.get(key): + s += "{}: {}\n".format(key, self.metadata.get(key)) + return s + + @property + def created_by(self): + return self.metadata.get(META_CREATED_BY_KEY) + + @property + def csar_version(self): + return self.metadata.get(META_CSAR_VERSION_KEY) + + @property + def meta_file_version(self): + return self.metadata.get(META_FILE_VERSION_KEY) + + @property + def entry_definitions(self): + return self.metadata.get(META_ENTRY_DEFINITIONS_KEY) + + @property + def entry_manifest_file(self): + return self.metadata.get(self.META_ENTRY_MANIFEST_FILE_KEY) + + @property + def entry_history_file(self): + return self.metadata.get(self.META_ENTRY_HISTORY_FILE_KEY) + + @property + def entry_tests_dir(self): + return self.metadata.get(self.META_ENTRY_TESTS_DIR_KEY) + + @property + def entry_licenses_dir(self): + return self.metadata.get(self.META_ENTRY_LICENSES_DIR_KEY) + + @property + def entry_certificate_file(self): + return self.metadata.get(self.META_ENTRY_CERT_FILE_KEY) + + +class ToscaMeta241(ToscaMeta): + # SOL004 v2.4.1 + META_ENTRY_MANIFEST_FILE_KEY = 'Entry-Manifest' + META_ENTRY_HISTORY_FILE_KEY = 'Entry-Change-Log' + META_ENTRY_TESTS_DIR_KEY = 'Entry-Tests' + META_ENTRY_LICENSES_DIR_KEY = 'Entry-Licenses' + META_ENTRY_CERT_FILE_KEY = 'Entry-Certificate' + REQUIRED_KEYS = [ META_FILE_VERSION_KEY, META_CSAR_VERSION_KEY, + META_CREATED_BY_KEY, META_ENTRY_DEFINITIONS_KEY, + ] + OPTIONAL_KEYS = [ META_ENTRY_MANIFEST_FILE_KEY, META_ENTRY_HISTORY_FILE_KEY, + META_ENTRY_LICENSES_DIR_KEY, META_ENTRY_TESTS_DIR_KEY, + META_ENTRY_CERT_FILE_KEY, + ] + + +class ToscaMeta261(ToscaMeta): + # SOL004 v2.6.1 + pass + + +def create_from_file(base_dir): + csar_metafile = os.path.join(base_dir, META_FILE) + if not os.path.exists(csar_metafile): + raise ValueError('Metadata file {0} is missing from the CSAR'.format(csar_metafile)) + LOG.debug('CSAR metadata file: {0}'.format(csar_metafile)) + LOG.debug('Attempting to parse CSAR metadata YAML') + with open(csar_metafile) as f: + metadata = yaml.safe_load(f) + LOG.debug('CSAR metadata:\n{0}'.format(pprint.pformat(metadata))) + # By default we assume it's SOL004 2.4.1 + cls = ToscaMeta241 + for key in metadata.keys(): + if key.startswith('ETSI-'): + cls = ToscaMeta261 + break + return cls(base_dir, + entry=metadata.get(META_ENTRY_DEFINITIONS_KEY), + manifest=metadata.get(cls.META_ENTRY_MANIFEST_FILE_KEY), + changelog=metadata.get(cls.META_ENTRY_HISTORY_FILE_KEY), + licenses=metadata.get(cls.META_ENTRY_LICENSES_DIR_KEY), + tests=metadata.get(cls.META_ENTRY_TESTS_DIR_KEY), + certificate=metadata.get(cls.META_ENTRY_CERT_FILE_KEY), + meta_file_version=metadata.get(META_FILE_VERSION_KEY), + meta_csar_version=metadata.get(META_CSAR_VERSION_KEY), + meta_created_by=metadata.get(META_CREATED_BY_KEY)) + |