Add CSAR processing support
Add support for processing CSAR files and include necessary unit tests. Note: Since CSAR files used do not already exist on github a temporary URL has been used. Once the patch merges a follow-on patch will be submitted to update the URL to a github URL. Change-Id: Ibf44be1368ed0144ecf415068b0ca5aea5aa6134 Partially-Implements: blueprint tosca-csar-translation
This commit is contained in:
@@ -11,18 +11,26 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import os.path
|
import os.path
|
||||||
|
import requests
|
||||||
import tempfile
|
import tempfile
|
||||||
import yaml
|
import yaml
|
||||||
import zipfile
|
import zipfile
|
||||||
|
|
||||||
from toscaparser.common.exception import ValidationError
|
from toscaparser.common.exception import ValidationError
|
||||||
from toscaparser.utils.gettextutils import _
|
from toscaparser.utils.gettextutils import _
|
||||||
|
from toscaparser.utils.urlutils import UrlUtils
|
||||||
|
|
||||||
|
try: # Python 2.x
|
||||||
|
from BytesIO import BytesIO
|
||||||
|
except ImportError: # Python 3.x
|
||||||
|
from io import BytesIO
|
||||||
|
|
||||||
|
|
||||||
class CSAR(object):
|
class CSAR(object):
|
||||||
|
|
||||||
def __init__(self, csar_file):
|
def __init__(self, csar_file, a_file=True):
|
||||||
self.csar_file = csar_file
|
self.csar_file = csar_file
|
||||||
|
self.a_file = a_file
|
||||||
self.is_validated = False
|
self.is_validated = False
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
@@ -31,10 +39,18 @@ class CSAR(object):
|
|||||||
self.is_validated = True
|
self.is_validated = True
|
||||||
|
|
||||||
# validate that the file exists
|
# validate that the file exists
|
||||||
if not os.path.isfile(self.csar_file):
|
if self.a_file and not os.path.isfile(self.csar_file):
|
||||||
err_msg = (_('The file %s does not exist.') % self.csar_file)
|
err_msg = (_('The file %s does not exist.') % self.csar_file)
|
||||||
raise ValidationError(message=err_msg)
|
raise ValidationError(message=err_msg)
|
||||||
|
|
||||||
|
if not self.a_file: # a URL
|
||||||
|
if not UrlUtils.validate_url(self.csar_file):
|
||||||
|
err_msg = (_('The URL %s does not exist.') % self.csar_file)
|
||||||
|
raise ValidationError(message=err_msg)
|
||||||
|
else:
|
||||||
|
response = requests.get(self.csar_file)
|
||||||
|
self.csar_file = BytesIO(response.content)
|
||||||
|
|
||||||
# validate that it is a valid zip file
|
# validate that it is a valid zip file
|
||||||
if not zipfile.is_zipfile(self.csar_file):
|
if not zipfile.is_zipfile(self.csar_file):
|
||||||
err_msg = (_('The file %s is not a valid zip file.')
|
err_msg = (_('The file %s is not a valid zip file.')
|
||||||
|
|||||||
BIN
toscaparser/tests/data/CSAR/csar_elk.zip
Normal file
BIN
toscaparser/tests/data/CSAR/csar_elk.zip
Normal file
Binary file not shown.
BIN
toscaparser/tests/data/CSAR/csar_wordpress.zip
Normal file
BIN
toscaparser/tests/data/CSAR/csar_wordpress.zip
Normal file
Binary file not shown.
@@ -58,10 +58,10 @@ topology_template:
|
|||||||
configure:
|
configure:
|
||||||
implementation: Scripts/MYSQLDatabase/configure.sh
|
implementation: Scripts/MYSQLDatabase/configure.sh
|
||||||
inputs:
|
inputs:
|
||||||
db_name: { get_property: [ SELF, db_name ] }
|
db_name: { get_property: [ SELF, name ] }
|
||||||
db_user: { get_property: [ SELF, db_user ] }
|
db_user: { get_property: [ SELF, user ] }
|
||||||
db_password: { get_property: [ SELF, db_password ] }
|
db_password: { get_property: [ SELF, password ] }
|
||||||
db_root_password: { get_property: [ mysql_dbms, dbms_root_password ] }
|
db_root_password: { get_property: [ mysql_dbms, root_password ] }
|
||||||
|
|
||||||
mysql_dbms:
|
mysql_dbms:
|
||||||
type: tosca.nodes.DBMS
|
type: tosca.nodes.DBMS
|
||||||
@@ -87,20 +87,21 @@ topology_template:
|
|||||||
Standard:
|
Standard:
|
||||||
create: Scripts/WebServer/install.sh
|
create: Scripts/WebServer/install.sh
|
||||||
start: Scripts/WebServer/start.sh
|
start: Scripts/WebServer/start.sh
|
||||||
server:
|
|
||||||
type: tosca.nodes.Compute
|
server:
|
||||||
capabilities:
|
type: tosca.nodes.Compute
|
||||||
host:
|
capabilities:
|
||||||
properties:
|
host:
|
||||||
disk_size: 10 GB
|
properties:
|
||||||
num_cpus: { get_input: cpus }
|
disk_size: 10 GB
|
||||||
mem_size: 4096 MB
|
num_cpus: { get_input: cpus }
|
||||||
os:
|
mem_size: 4096 MB
|
||||||
properties:
|
os:
|
||||||
architecture: x86_64
|
properties:
|
||||||
type: Linux
|
architecture: x86_64
|
||||||
distribution: Fedora
|
type: Linux
|
||||||
version: 18.0
|
distribution: Fedora
|
||||||
|
version: 18.0
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
website_url:
|
website_url:
|
||||||
|
|||||||
@@ -423,3 +423,14 @@ class ToscaTemplateTest(TestCase):
|
|||||||
'tosca_single_instance_wordpress_with_url_import.yaml')
|
'tosca_single_instance_wordpress_with_url_import.yaml')
|
||||||
tosca = ToscaTemplate(tosca_tpl, False)
|
tosca = ToscaTemplate(tosca_tpl, False)
|
||||||
self.assertTrue(tosca.topology_template.custom_defs)
|
self.assertTrue(tosca.topology_template.custom_defs)
|
||||||
|
|
||||||
|
def test_csar_parsing_wordpress(self):
|
||||||
|
csar_archive = os.path.join(
|
||||||
|
os.path.dirname(os.path.abspath(__file__)),
|
||||||
|
'data/CSAR/csar_wordpress.zip')
|
||||||
|
self.assertTrue(ToscaTemplate(csar_archive))
|
||||||
|
|
||||||
|
def test_csar_parsing_elk_url_based(self):
|
||||||
|
csar_archive = ('https://ibm.box.com/shared/static/'
|
||||||
|
'k9vtus4jes1epl7vfojbcscgsd80inzv.zip')
|
||||||
|
self.assertTrue(ToscaTemplate(csar_archive, False))
|
||||||
|
|||||||
@@ -12,15 +12,15 @@
|
|||||||
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
from toscaparser.common.exception import InvalidTemplateVersion
|
from toscaparser.common.exception import InvalidTemplateVersion
|
||||||
from toscaparser.common.exception import MissingRequiredFieldError
|
from toscaparser.common.exception import MissingRequiredFieldError
|
||||||
from toscaparser.common.exception import UnknownFieldError
|
from toscaparser.common.exception import UnknownFieldError
|
||||||
|
import toscaparser.imports
|
||||||
|
from toscaparser.prereq.csar import CSAR
|
||||||
from toscaparser.topology_template import TopologyTemplate
|
from toscaparser.topology_template import TopologyTemplate
|
||||||
from toscaparser.tpl_relationship_graph import ToscaGraph
|
from toscaparser.tpl_relationship_graph import ToscaGraph
|
||||||
|
|
||||||
import toscaparser.imports
|
|
||||||
import toscaparser.utils.urlutils
|
|
||||||
import toscaparser.utils.yamlparser
|
import toscaparser.utils.yamlparser
|
||||||
|
|
||||||
|
|
||||||
@@ -49,9 +49,9 @@ class ToscaTemplate(object):
|
|||||||
|
|
||||||
'''Load the template data.'''
|
'''Load the template data.'''
|
||||||
def __init__(self, path, a_file=True, parsed_params=None):
|
def __init__(self, path, a_file=True, parsed_params=None):
|
||||||
self.tpl = YAML_LOADER(path, a_file)
|
|
||||||
self.path = path
|
|
||||||
self.a_file = a_file
|
self.a_file = a_file
|
||||||
|
self.path = self._get_path(path)
|
||||||
|
self.tpl = YAML_LOADER(self.path, self.a_file)
|
||||||
self.parsed_params = parsed_params
|
self.parsed_params = parsed_params
|
||||||
self._validate_field()
|
self._validate_field()
|
||||||
self.version = self._tpl_version()
|
self.version = self._tpl_version()
|
||||||
@@ -151,3 +151,17 @@ class ToscaTemplate(object):
|
|||||||
raise InvalidTemplateVersion(
|
raise InvalidTemplateVersion(
|
||||||
what=version,
|
what=version,
|
||||||
valid_versions=', '. join(self.VALID_TEMPLATE_VERSIONS))
|
valid_versions=', '. join(self.VALID_TEMPLATE_VERSIONS))
|
||||||
|
|
||||||
|
def _get_path(self, path):
|
||||||
|
if path.lower().endswith('.yaml'):
|
||||||
|
return path
|
||||||
|
elif path.lower().endswith('.zip'):
|
||||||
|
# a CSAR archive
|
||||||
|
csar = CSAR(path, self.a_file)
|
||||||
|
csar.validate()
|
||||||
|
folder = csar.decompress()
|
||||||
|
self.a_file = True # the file has been decompressed locally
|
||||||
|
return os.path.join(folder, csar.get_main_template())
|
||||||
|
else:
|
||||||
|
raise ValueError(_("%(path)s is not a valid file.")
|
||||||
|
% {'path': path})
|
||||||
|
|||||||
Reference in New Issue
Block a user