Convert script line endings for the target OS

This patch adds 'binary' parameter to ResourceManager 'string'
method. It allows to open text files in 'rU' mode which recognizes
all types of newlines, and binary files in 'rb' mode to prevent
their corruption.

Change-Id: I505070df187dfd910e68c555319e3ef92ce2c826
Closes-bug: #1496376
This commit is contained in:
Valerii Kovalchuk
2016-04-29 15:52:31 +03:00
parent d8ccb215be
commit 9d0c88a47b
4 changed files with 65 additions and 6 deletions

View File

@@ -218,7 +218,7 @@ class Agent(object):
for script in script_files:
script_path = os.path.join(scripts_folder, script)
script_path = base64.encode_as_text(script_path) + "\n"
scripts.append(resources.string(script_path))
scripts.append(resources.string(script_path, binary=True))
template['Scripts'] = scripts
return template
@@ -288,11 +288,13 @@ class Agent(object):
def _get_body(self, file, resources, folder):
use_base64 = self._is_base64(file)
if use_base64 and file.startswith('<') and file.endswith('>'):
file = file[1: -1]
body = resources.string(os.path.join(folder, file))
if use_base64:
path = os.path.join(folder, file[1: -1])
body = resources.string(path, binary=True)
body = base64.encode_as_text(body) + "\n"
else:
path = os.path.join(folder, file)
body = resources.string(path)
return body
def _is_base64(self, file):

View File

@@ -52,9 +52,10 @@ class ResourceManager(object):
@staticmethod
@specs.parameter('owner', dsl.MuranoTypeParameter(nullable=True))
@specs.inject('receiver', yaqltypes.Receiver())
def string(receiver, name, owner=None):
def string(receiver, name, owner=None, binary=False):
path = ResourceManager._get_package(owner, receiver).get_resource(name)
with open(path) as file:
mode = 'rb' if binary else 'rU'
with open(path, mode) as file:
return file.read()
@classmethod

View File

@@ -13,8 +13,10 @@
# under the License.
import os
import tempfile
import mock
from oslo_serialization import base64
import yaml as yamllib
from murano.dsl import murano_object
@@ -309,3 +311,52 @@ class TestExecutionPlan(base.MuranoTestCase):
mock_uuid4 = mock.patch('uuid.uuid4').start()
mock_uuid4.side_effect = [FakeUUID(v) for v in values]
return mock_uuid4
@mock.patch('murano.engine.system.resource_manager.ResourceManager'
'._get_package')
def test_file_line_endings(self, _get_package):
class FakeResources(object):
"""Class with only string() method from ResourceManager class"""
@staticmethod
def string(name, owner=None, binary=False):
return resource_manager.ResourceManager.string(
receiver=None, name=name, owner=owner, binary=binary)
# make path equal to provided name inside resources.string()
package = mock.Mock()
package.get_resource.side_effect = lambda m: m
_get_package.return_value = package
text = b"First line\nSecond line\rThird line\r\nFourth line"
modified_text = u"First line\nSecond line\nThird line\nFourth line"
encoded_text = base64.encode_as_text(text) + "\n"
resources = FakeResources()
with tempfile.NamedTemporaryFile() as script_file:
script_file.write(text)
script_file.file.flush()
os.fsync(script_file.file.fileno())
# check that data has been written correctly
script_file.seek(0)
file_data = script_file.read()
self.assertEqual(text, file_data)
# check resources.string() output
# text file
result = resources.string(script_file.name)
self.assertEqual(modified_text, result)
# binary file
result = resources.string(script_file.name, binary=True)
self.assertEqual(text, result)
# check _get_body() output
filename = os.path.basename(script_file.name)
folder = os.path.dirname(script_file.name)
# text file
body = self.agent._get_body(filename, resources, folder)
self.assertEqual(modified_text, body)
# binary file
filename = '<{0}>'.format(filename)
body = self.agent._get_body(filename, resources, folder)
self.assertEqual(encoded_text, body)

View File

@@ -0,0 +1,5 @@
---
fixes:
- Text script files are opened in 'rU' mode which recognizes all types of
newlines, and binary files are opened in 'rb' mode to prevent their
corruption.