File Downloable Feature
It involves the possibility of having File URL in execution plans. These URLs will not be downloaded in murano, but in murano-agent. This feature is related to the blueprint https://blueprints.launchpad.net/murano/+spec/conf-language-support Change-Id: I01f32806f61ba424135ddb26ef87d7a046d93cf9
This commit is contained in:
parent
42c320a085
commit
86bec233c5
@ -18,6 +18,7 @@ import datetime
|
||||
import logging
|
||||
import os
|
||||
import types
|
||||
import urlparse
|
||||
import uuid
|
||||
|
||||
import eventlet.event
|
||||
@ -228,31 +229,79 @@ class Agent(murano_object.MuranoObject):
|
||||
files = {}
|
||||
for file_id, file_descr in template['Files'].items():
|
||||
files[file_descr['Name']] = file_id
|
||||
|
||||
for name, script in template.get('Scripts', {}).items():
|
||||
if 'EntryPoint' not in script:
|
||||
raise ValueError('No entry point in script ' + name)
|
||||
script['EntryPoint'] = self._place_file(
|
||||
scripts_folder, script['EntryPoint'],
|
||||
template, files, resources)
|
||||
if 'Files' in script:
|
||||
for i in range(0, len(script['Files'])):
|
||||
script['Files'][i] = self._place_file(
|
||||
scripts_folder, script['Files'][i],
|
||||
template, files, resources)
|
||||
|
||||
if 'Application' in script['Type']:
|
||||
script['EntryPoint'] = self._place_file(
|
||||
scripts_folder, script['EntryPoint'],
|
||||
template, files, resources)
|
||||
scripts_files = script['Files']
|
||||
script['Files'] = []
|
||||
for file in scripts_files:
|
||||
file_id = self._place_file(scripts_folder, file,
|
||||
template, files, resources)
|
||||
if self._is_url(file):
|
||||
script['Files'].append(file)
|
||||
else:
|
||||
script['Files'].append(file_id)
|
||||
return template
|
||||
|
||||
def _place_file(self, folder, name, template, files, resources):
|
||||
def _is_url(self, file):
|
||||
file = self._get_url(file)
|
||||
parts = urlparse.urlsplit(file)
|
||||
if not parts.scheme or not parts.netloc:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def _get_url(self, file):
|
||||
if isinstance(file, dict):
|
||||
return file.values()[0]
|
||||
else:
|
||||
return file
|
||||
|
||||
def _get_name(self, file):
|
||||
if isinstance(file, dict):
|
||||
name = file.keys()[0]
|
||||
else:
|
||||
name = file
|
||||
|
||||
if self._is_url(name):
|
||||
name = name[name.rindex('/') + 1:len(name)]
|
||||
return name
|
||||
|
||||
def _get_file(self, file):
|
||||
if isinstance(file, dict):
|
||||
return file.values()[0]
|
||||
else:
|
||||
return file
|
||||
|
||||
def _place_file(self, folder, file, template, files, resources):
|
||||
name = self._get_name(file)
|
||||
file = self._get_file(file)
|
||||
file_id = uuid.uuid4().hex
|
||||
|
||||
if self._is_url(file):
|
||||
template['Files'][file_id] = {
|
||||
'Name': str(name),
|
||||
'URL': file,
|
||||
'Type': 'Downloadable'}
|
||||
return file_id
|
||||
|
||||
use_base64 = False
|
||||
if name.startswith('<') and name.endswith('>'):
|
||||
if file.startswith('<') and file.endswith('>'):
|
||||
use_base64 = True
|
||||
name = name[1:len(name) - 1]
|
||||
if name in files:
|
||||
if '<' in name:
|
||||
name = file[1:len(file) - 1]
|
||||
|
||||
if file in files:
|
||||
return files[name]
|
||||
|
||||
file_id = uuid.uuid4().hex
|
||||
body_type = 'Base64' if use_base64 else 'Text'
|
||||
body = resources.string(os.path.join(folder, name))
|
||||
body = resources.string(os.path.join(folder, file))
|
||||
if use_base64:
|
||||
body = body.encode('base64')
|
||||
|
||||
|
0
murano/tests/unit/engine/__init__.py
Normal file
0
murano/tests/unit/engine/__init__.py
Normal file
0
murano/tests/unit/engine/system/__init__.py
Normal file
0
murano/tests/unit/engine/system/__init__.py
Normal file
@ -0,0 +1,21 @@
|
||||
FormatVersion: 2.0.0
|
||||
Version: 1.0.0
|
||||
Name: Deploy Telnet
|
||||
|
||||
Parameters:
|
||||
appName: $appName
|
||||
|
||||
Body: |
|
||||
return deploy(args.appName).stdout
|
||||
|
||||
Scripts:
|
||||
deploy:
|
||||
Type: Application
|
||||
Version: 1.0.0
|
||||
EntryPoint: deployTelnet.sh
|
||||
Files:
|
||||
- installer.sh
|
||||
- common.sh
|
||||
Options:
|
||||
captureStdout: true
|
||||
captureStderr: true
|
@ -0,0 +1,21 @@
|
||||
FormatVersion: 2.0.0
|
||||
Version: 1.0.0
|
||||
Name: Deploy Tomcat
|
||||
|
||||
Parameters:
|
||||
appName: $appName
|
||||
|
||||
Body: |
|
||||
return deploy(args.appName).stdout
|
||||
|
||||
Scripts:
|
||||
deploy:
|
||||
Type: Application
|
||||
Version: 1.0.0
|
||||
EntryPoint: deployTomcat.sh
|
||||
Files:
|
||||
- installer: <installer.sh>
|
||||
- <common.sh>
|
||||
Options:
|
||||
captureStdout: true
|
||||
captureStderr: true
|
@ -0,0 +1,21 @@
|
||||
FormatVersion: 2.0.0
|
||||
Version: 1.0.0
|
||||
Name: Deploy Chef
|
||||
|
||||
Parameters:
|
||||
appName: $appName
|
||||
|
||||
Body: |
|
||||
return deploy(args.appName).stdout
|
||||
|
||||
Scripts:
|
||||
deploy:
|
||||
Type: Chef
|
||||
Version: 1.0.0
|
||||
EntryPoint: cookbook/recipe
|
||||
Files:
|
||||
- https://github.com/tomcat.git
|
||||
- java: https://github.com/java.git
|
||||
Options:
|
||||
captureStdout: true
|
||||
captureStderr: true
|
214
murano/tests/unit/engine/system/test_agent.py
Normal file
214
murano/tests/unit/engine/system/test_agent.py
Normal file
@ -0,0 +1,214 @@
|
||||
# Copyright (c) 2015 Telefonica I+D
|
||||
#
|
||||
# Licensed 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 mock
|
||||
import os
|
||||
|
||||
import yaml as yamllib
|
||||
|
||||
from murano.dsl import murano_class
|
||||
from murano.dsl import object_store
|
||||
import murano.engine.system.agent as agent
|
||||
import murano.engine.system.resource_manager as resource
|
||||
from murano.tests.unit import base
|
||||
|
||||
|
||||
class TestExecutionPlan(base.MuranoTestCase):
|
||||
def setUp(self):
|
||||
super(TestExecutionPlan, self).setUp()
|
||||
if hasattr(yamllib, 'CSafeLoader'):
|
||||
self.yaml_loader = yamllib.CSafeLoader
|
||||
else:
|
||||
self.yaml_loader = yamllib.SafeLoader
|
||||
|
||||
self.mock_murano_class = mock.Mock(spec=murano_class.MuranoClass)
|
||||
self.mock_murano_class.name = 'io.murano.system.Agent'
|
||||
self.mock_murano_class.parents = []
|
||||
self.mock_object_store = mock.Mock(spec=object_store.ObjectStore)
|
||||
self.agent = agent.Agent(self.mock_murano_class, None,
|
||||
self.mock_object_store, None)
|
||||
self.resources = mock.Mock(spec=resource.ResourceManager)
|
||||
self.resources.string.return_value = 'text'
|
||||
self.uuids = ['ID1', 'ID2', 'ID3', 'ID4']
|
||||
self.mock_uuid = self._stub_uuid(self.uuids)
|
||||
self.addCleanup(mock.patch.stopall)
|
||||
|
||||
def _read(self, path):
|
||||
execution_plan_dir = os.path.abspath(
|
||||
os.path.join(__file__, '../execution_plans/')
|
||||
)
|
||||
with open(execution_plan_dir + "/" + path) as file:
|
||||
return file.read()
|
||||
|
||||
def test_execution_plan_v2_application_type(self):
|
||||
template = yamllib.load(
|
||||
self._read('application.template'),
|
||||
Loader=self.yaml_loader)
|
||||
template = self.agent.buildExecutionPlan(template, self.resources)
|
||||
|
||||
self.assertEqual(template, self._get_application())
|
||||
|
||||
def test_execution_plan_v2_chef_type(self):
|
||||
template = yamllib.load(
|
||||
self._read('chef.template'),
|
||||
Loader=self.yaml_loader)
|
||||
template = self.agent.buildExecutionPlan(template, self.resources)
|
||||
self.assertEqual(template, self._get_chef())
|
||||
|
||||
def test_execution_plan_v3_telnet_application(self):
|
||||
template = yamllib.load(
|
||||
self._read('DeployTelnet.template'),
|
||||
Loader=self.yaml_loader)
|
||||
template = self.agent.buildExecutionPlan(template, self.resources)
|
||||
self.assertEqual(template, self._get_telnet_application())
|
||||
|
||||
def _get_application(self):
|
||||
return {
|
||||
'Action': 'Execute',
|
||||
'Body': 'return deploy(args.appName).stdout\n',
|
||||
'Files': {
|
||||
self.uuids[1]: {
|
||||
'Body': 'text',
|
||||
'BodyType': 'Text',
|
||||
'Name': 'deployTomcat.sh'
|
||||
},
|
||||
self.uuids[2]: {
|
||||
'Body': 'dGV4dA==\n',
|
||||
'BodyType': 'Base64',
|
||||
'Name': 'installer'
|
||||
},
|
||||
self.uuids[3]: {
|
||||
'Body': 'dGV4dA==\n',
|
||||
'BodyType': 'Base64',
|
||||
'Name': 'common.sh'
|
||||
}
|
||||
},
|
||||
'FormatVersion': '2.0.0',
|
||||
'ID': self.uuids[0],
|
||||
'Name': 'Deploy Tomcat',
|
||||
'Parameters': {
|
||||
'appName': '$appName'
|
||||
},
|
||||
'Scripts': {
|
||||
'deploy': {
|
||||
'EntryPoint': self.uuids[1],
|
||||
'Files': [
|
||||
self.uuids[2],
|
||||
self.uuids[3]
|
||||
],
|
||||
'Options': {
|
||||
'captureStderr': True,
|
||||
'captureStdout': True
|
||||
},
|
||||
'Type': 'Application',
|
||||
'Version': '1.0.0'
|
||||
}
|
||||
},
|
||||
'Version': '1.0.0'
|
||||
}
|
||||
|
||||
def _get_chef(self):
|
||||
return {
|
||||
'Action': 'Execute',
|
||||
'Body': 'return deploy(args.appName).stdout\n',
|
||||
'Files': {
|
||||
self.uuids[1]: {
|
||||
'Name': 'tomcat.git',
|
||||
'Type': 'Downloadable',
|
||||
'URL': 'https://github.com/tomcat.git'
|
||||
},
|
||||
self.uuids[2]: {
|
||||
'Name': 'java',
|
||||
'Type': 'Downloadable',
|
||||
'URL': 'https://github.com/java.git'
|
||||
},
|
||||
|
||||
},
|
||||
'FormatVersion': '2.0.0',
|
||||
'ID': self.uuids[0],
|
||||
'Name': 'Deploy Chef',
|
||||
'Parameters': {
|
||||
'appName': '$appName'
|
||||
},
|
||||
'Scripts': {
|
||||
'deploy': {
|
||||
'EntryPoint': 'cookbook/recipe',
|
||||
'Files': [
|
||||
'https://github.com/tomcat.git',
|
||||
{'java': 'https://github.com/java.git'}
|
||||
],
|
||||
'Options': {
|
||||
'captureStderr': True,
|
||||
'captureStdout': True
|
||||
},
|
||||
'Type': 'Chef',
|
||||
'Version': '1.0.0'
|
||||
}
|
||||
},
|
||||
'Version': '1.0.0'
|
||||
}
|
||||
|
||||
def _get_telnet_application(self):
|
||||
return {
|
||||
'Action': 'Execute',
|
||||
'Body': 'return deploy(args.appName).stdout\n',
|
||||
'Files': {
|
||||
self.uuids[1]: {
|
||||
'Body': 'text',
|
||||
'BodyType': 'Text',
|
||||
'Name': 'deployTelnet.sh'
|
||||
},
|
||||
self.uuids[2]: {
|
||||
'Body': 'text',
|
||||
'BodyType': 'Text',
|
||||
'Name': 'installer.sh'
|
||||
},
|
||||
self.uuids[3]: {
|
||||
'Body': 'text',
|
||||
'BodyType': 'Text',
|
||||
'Name': 'common.sh'
|
||||
}
|
||||
},
|
||||
'FormatVersion': '2.0.0',
|
||||
'ID': self.uuids[0],
|
||||
'Name': 'Deploy Telnet',
|
||||
'Parameters': {
|
||||
'appName': '$appName'
|
||||
},
|
||||
'Scripts': {
|
||||
'deploy': {
|
||||
'EntryPoint': self.uuids[1],
|
||||
'Files': [
|
||||
self.uuids[2],
|
||||
self.uuids[3]
|
||||
],
|
||||
'Options': {
|
||||
'captureStderr': True,
|
||||
'captureStdout': True
|
||||
},
|
||||
'Type': 'Application',
|
||||
'Version': '1.0.0'
|
||||
}
|
||||
},
|
||||
'Version': '1.0.0'
|
||||
}
|
||||
|
||||
def _stub_uuid(self, values=[]):
|
||||
class FakeUUID(object):
|
||||
def __init__(self, v):
|
||||
self.hex = v
|
||||
|
||||
mock_uuid4 = mock.patch('uuid.uuid4').start()
|
||||
mock_uuid4.side_effect = [FakeUUID(v) for v in values]
|
||||
return mock_uuid4
|
Loading…
x
Reference in New Issue
Block a user