Add rally use command
This adds a new group of commands : 'rally use' the first implemented is 'rally use deployment <deploy_id>' As it is not possible in python to export globaly an env var,it saves the variable in a file at ~/.rally/deployment like : RALLY_DEPLOYMENT=1234abcd For each command that takes a deploy_id as parameter, this parameter is now optional. The algorithm to find the deploy_id is as follows : - If the --deploy-id param is set, use it - If the environ contains the key 'RALLY_DEPLOYMENT', use it - load the content of ~/.rally/deployment and if it contains the key RALLY_DEPLOYMENT, use it - Else, raise an InvalidArgumentException Note that I have not been able to use the default arg in @cliutils.args because it is called before the effective method call. Setting deploy_id=envutils.default_deployment_id() has the same problem Partially implements blueprint: rally-use-command Change-Id: I1e62e26d259bd9e81f1c008058ee9ce91cc3290c
This commit is contained in:
31
rally/cmd/envutils.py
Normal file
31
rally/cmd/envutils.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# Copyright 2013: Mirantis Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# 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 os
|
||||||
|
|
||||||
|
from rally import exceptions
|
||||||
|
from rally import fileutils
|
||||||
|
|
||||||
|
|
||||||
|
def default_deployment_id():
|
||||||
|
try:
|
||||||
|
deploy_id = os.environ['RALLY_DEPLOYMENT']
|
||||||
|
except KeyError:
|
||||||
|
fileutils.load_env_file(os.path.expanduser('~/.rally/deployment'))
|
||||||
|
try:
|
||||||
|
deploy_id = os.environ['RALLY_DEPLOYMENT']
|
||||||
|
except KeyError:
|
||||||
|
raise exceptions.InvalidArgumentsException(
|
||||||
|
"deploy-id argument is missing")
|
||||||
|
return deploy_id
|
@@ -21,11 +21,14 @@ import json
|
|||||||
import pprint
|
import pprint
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
import os
|
||||||
import prettytable
|
import prettytable
|
||||||
|
|
||||||
from rally.cmd import cliutils
|
from rally.cmd import cliutils
|
||||||
|
from rally.cmd import envutils
|
||||||
from rally import db
|
from rally import db
|
||||||
from rally import exceptions
|
from rally import exceptions
|
||||||
|
from rally import fileutils
|
||||||
from rally.openstack.common.gettextutils import _
|
from rally.openstack.common.gettextutils import _
|
||||||
from rally.orchestrator import api
|
from rally.orchestrator import api
|
||||||
from rally import processing
|
from rally import processing
|
||||||
@@ -48,18 +51,19 @@ class DeploymentCommands(object):
|
|||||||
deployment = api.create_deploy(config, name)
|
deployment = api.create_deploy(config, name)
|
||||||
self.list(deployment_list=[deployment])
|
self.list(deployment_list=[deployment])
|
||||||
|
|
||||||
@cliutils.args('--deploy-id', dest='deploy_id', type=str, required=True,
|
@cliutils.args('--deploy-id', dest='deploy_id', type=str, required=False,
|
||||||
help='UUID of a deployment.')
|
help='UUID of a deployment.')
|
||||||
def recreate(self, deploy_id):
|
def recreate(self, deploy_id=None):
|
||||||
"""Destroy and create an existing deployment.
|
"""Destroy and create an existing deployment.
|
||||||
|
|
||||||
:param deploy_id: a UUID of the deployment
|
:param deploy_id: a UUID of the deployment
|
||||||
"""
|
"""
|
||||||
|
deploy_id = deploy_id or envutils.default_deployment_id()
|
||||||
api.recreate_deploy(deploy_id)
|
api.recreate_deploy(deploy_id)
|
||||||
|
|
||||||
@cliutils.args('--deploy-id', dest='deploy_id', type=str, required=True,
|
@cliutils.args('--deploy-id', dest='deploy_id', type=str, required=False,
|
||||||
help='UUID of a deployment.')
|
help='UUID of a deployment.')
|
||||||
def destroy(self, deploy_id):
|
def destroy(self, deploy_id=None):
|
||||||
"""Destroy the deployment.
|
"""Destroy the deployment.
|
||||||
|
|
||||||
Release resources that are allocated for the deployment. The
|
Release resources that are allocated for the deployment. The
|
||||||
@@ -67,6 +71,7 @@ class DeploymentCommands(object):
|
|||||||
|
|
||||||
:param deploy_id: a UUID of the deployment
|
:param deploy_id: a UUID of the deployment
|
||||||
"""
|
"""
|
||||||
|
deploy_id = deploy_id or envutils.default_deployment_id()
|
||||||
api.destroy_deploy(deploy_id)
|
api.destroy_deploy(deploy_id)
|
||||||
|
|
||||||
def list(self, deployment_list=None):
|
def list(self, deployment_list=None):
|
||||||
@@ -81,23 +86,25 @@ class DeploymentCommands(object):
|
|||||||
|
|
||||||
print(table)
|
print(table)
|
||||||
|
|
||||||
@cliutils.args('--deploy-id', dest='deploy_id', type=str, required=True,
|
@cliutils.args('--deploy-id', dest='deploy_id', type=str, required=False,
|
||||||
help='UUID of a deployment.')
|
help='UUID of a deployment.')
|
||||||
def config(self, deploy_id):
|
def config(self, deploy_id=None):
|
||||||
"""Print on stdout a config of the deployment in JSON format.
|
"""Print on stdout a config of the deployment in JSON format.
|
||||||
|
|
||||||
:param deploy_id: a UUID of the deployment
|
:param deploy_id: a UUID of the deployment
|
||||||
"""
|
"""
|
||||||
|
deploy_id = deploy_id or envutils.default_deployment_id()
|
||||||
deploy = db.deployment_get(deploy_id)
|
deploy = db.deployment_get(deploy_id)
|
||||||
print(json.dumps(deploy['config']))
|
print(json.dumps(deploy['config']))
|
||||||
|
|
||||||
@cliutils.args('--deploy-id', dest='deploy_id', type=str, required=True,
|
@cliutils.args('--deploy-id', dest='deploy_id', type=str, required=False,
|
||||||
help='UUID of a deployment.')
|
help='UUID of a deployment.')
|
||||||
def endpoint(self, deploy_id):
|
def endpoint(self, deploy_id=None):
|
||||||
"""Print endpoint of the deployment.
|
"""Print endpoint of the deployment.
|
||||||
|
|
||||||
:param deploy_id: a UUID of the deployment
|
:param deploy_id: a UUID of the deployment
|
||||||
"""
|
"""
|
||||||
|
deploy_id = deploy_id or envutils.default_deployment_id()
|
||||||
headers = ['auth_url', 'username', 'password', 'tenant_name']
|
headers = ['auth_url', 'username', 'password', 'tenant_name']
|
||||||
table = prettytable.PrettyTable(headers)
|
table = prettytable.PrettyTable(headers)
|
||||||
endpoint = db.deployment_get(deploy_id)['endpoint']
|
endpoint = db.deployment_get(deploy_id)['endpoint']
|
||||||
@@ -107,16 +114,17 @@ class DeploymentCommands(object):
|
|||||||
|
|
||||||
class TaskCommands(object):
|
class TaskCommands(object):
|
||||||
|
|
||||||
@cliutils.args('--deploy-id', type=str, dest='deploy_id', required=True,
|
@cliutils.args('--deploy-id', type=str, dest='deploy_id', required=False,
|
||||||
help='UUID of the deployment')
|
help='UUID of the deployment')
|
||||||
@cliutils.args('--task',
|
@cliutils.args('--task',
|
||||||
help='Path to the file with full configuration of task')
|
help='Path to the file with full configuration of task')
|
||||||
def start(self, deploy_id, task):
|
def start(self, task, deploy_id=None):
|
||||||
"""Run a benchmark task.
|
"""Run a benchmark task.
|
||||||
|
|
||||||
:param deploy_id: a UUID of a deployment
|
|
||||||
:param task: a file with json configration
|
:param task: a file with json configration
|
||||||
|
:param deploy_id: a UUID of a deployment
|
||||||
"""
|
"""
|
||||||
|
deploy_id = deploy_id or envutils.default_deployment_id()
|
||||||
with open(task) as task_file:
|
with open(task) as task_file:
|
||||||
config_dict = json.load(task_file)
|
config_dict = json.load(task_file)
|
||||||
try:
|
try:
|
||||||
@@ -285,6 +293,20 @@ class TaskCommands(object):
|
|||||||
print("Plot type '%s' not supported." % plot_type)
|
print("Plot type '%s' not supported." % plot_type)
|
||||||
|
|
||||||
|
|
||||||
|
class UseCommands(object):
|
||||||
|
|
||||||
|
def deployment(self, deploy_id):
|
||||||
|
"""Set the RALLY_DEPLOYMENT env var to be used by all CLI commands
|
||||||
|
|
||||||
|
:param deploy_id: a UUID of a deployment
|
||||||
|
"""
|
||||||
|
print('Using deployment : %s' % deploy_id)
|
||||||
|
if not os.path.exists(os.path.expanduser('~/.rally/')):
|
||||||
|
os.makedirs(os.path.expanduser('~/.rally/'))
|
||||||
|
expanded_path = os.path.expanduser('~/.rally/deployment')
|
||||||
|
fileutils.update_env_file(expanded_path, 'RALLY_DEPLOYMENT', deploy_id)
|
||||||
|
|
||||||
|
|
||||||
def deprecated():
|
def deprecated():
|
||||||
print("\n\n---\n\nopenstack-rally and openstack-rally-manage are "
|
print("\n\n---\n\nopenstack-rally and openstack-rally-manage are "
|
||||||
"deprecated, please use rally and rally-manage\n\n---\n\n")
|
"deprecated, please use rally and rally-manage\n\n---\n\n")
|
||||||
@@ -295,6 +317,7 @@ def main():
|
|||||||
categories = {
|
categories = {
|
||||||
'task': TaskCommands,
|
'task': TaskCommands,
|
||||||
'deployment': DeploymentCommands,
|
'deployment': DeploymentCommands,
|
||||||
|
'use': UseCommands,
|
||||||
}
|
}
|
||||||
cliutils.run(sys.argv, categories)
|
cliutils.run(sys.argv, categories)
|
||||||
|
|
||||||
|
72
rally/fileutils.py
Normal file
72
rally/fileutils.py
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
# Copyright 2013: Mirantis Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# 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 os
|
||||||
|
|
||||||
|
|
||||||
|
def _read_env_file(path, except_env=None):
|
||||||
|
"""Read the environment variable file.
|
||||||
|
|
||||||
|
:param path: the path of the file
|
||||||
|
:param except_env: the environment variable to avoid in the output
|
||||||
|
|
||||||
|
:returns: the content of the original file except the line starting with
|
||||||
|
the except_env parameter
|
||||||
|
"""
|
||||||
|
output = []
|
||||||
|
if os.path.exists(path):
|
||||||
|
with open(path, 'r') as env_file:
|
||||||
|
content = env_file.readlines()
|
||||||
|
print(content)
|
||||||
|
for line in content:
|
||||||
|
if except_env is None or \
|
||||||
|
not line.startswith("%s=" % except_env):
|
||||||
|
output.append(line)
|
||||||
|
return output
|
||||||
|
|
||||||
|
|
||||||
|
def load_env_file(path):
|
||||||
|
"""Load the environment variable file into os.environ.
|
||||||
|
|
||||||
|
:param path: the path of the file
|
||||||
|
"""
|
||||||
|
if os.path.exists(path):
|
||||||
|
content = _read_env_file(path)
|
||||||
|
for line in content:
|
||||||
|
(key, sep, value) = line.partition("=")
|
||||||
|
os.environ[key] = value.rstrip()
|
||||||
|
|
||||||
|
|
||||||
|
def _rewrite_env_file(path, initial_content):
|
||||||
|
"""Rewrite the environment variable file.
|
||||||
|
|
||||||
|
:param path: the path of the file
|
||||||
|
:param initial_content: the original content of the file
|
||||||
|
"""
|
||||||
|
with open(path, 'w+') as env_file:
|
||||||
|
for line in initial_content:
|
||||||
|
env_file.write(line)
|
||||||
|
|
||||||
|
|
||||||
|
def update_env_file(path, env_key, env_value):
|
||||||
|
"""Update the environment variable file.
|
||||||
|
|
||||||
|
:param path: the path of the file
|
||||||
|
:param env_key: the key to update
|
||||||
|
:param env_value: the value of the property to update
|
||||||
|
"""
|
||||||
|
output = _read_env_file(path, env_key)
|
||||||
|
output.append('%s=%s' % (env_key, env_value))
|
||||||
|
_rewrite_env_file(path, output)
|
38
tests/cmd/test_envutils.py
Normal file
38
tests/cmd/test_envutils.py
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# Copyright 2013: Mirantis Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
|
||||||
|
from rally.cmd import envutils
|
||||||
|
from rally import exceptions
|
||||||
|
from rally.openstack.common import test
|
||||||
|
|
||||||
|
|
||||||
|
class EnvUtilsTestCase(test.BaseTestCase):
|
||||||
|
|
||||||
|
@mock.patch.dict(os.environ, values={'RALLY_DEPLOYMENT': 'my_deploy_id'},
|
||||||
|
clear=True)
|
||||||
|
def test_get_deployment_id_in_env(self):
|
||||||
|
deploy_id = envutils.default_deployment_id()
|
||||||
|
self.assertEqual('my_deploy_id', deploy_id)
|
||||||
|
|
||||||
|
@mock.patch.dict(os.environ, values={}, clear=True)
|
||||||
|
@mock.patch('rally.cmd.envutils.fileutils.load_env_file')
|
||||||
|
def test_get_deployment_id_with_exception(self, mock_file):
|
||||||
|
self.assertRaises(exceptions.InvalidArgumentsException,
|
||||||
|
envutils.default_deployment_id)
|
||||||
|
mock_file.assert_called_once_with(os.path.expanduser(
|
||||||
|
'~/.rally/deployment'))
|
@@ -14,9 +14,11 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
import os
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from rally.cmd import main
|
from rally.cmd import main
|
||||||
|
from rally import exceptions
|
||||||
from rally.openstack.common import test
|
from rally.openstack.common import test
|
||||||
|
|
||||||
|
|
||||||
@@ -39,10 +41,16 @@ class TaskCommandsTestCase(test.BaseTestCase):
|
|||||||
def test_start(self, mock_api, mock_create_task,
|
def test_start(self, mock_api, mock_create_task,
|
||||||
mock_task_detailed):
|
mock_task_detailed):
|
||||||
deploy_id = str(uuid.uuid4())
|
deploy_id = str(uuid.uuid4())
|
||||||
self.task.start(deploy_id, 'path_to_config.json')
|
self.task.start('path_to_config.json', deploy_id,)
|
||||||
mock_api.assert_called_once_with(deploy_id, {u'some': u'json'},
|
mock_api.assert_called_once_with(deploy_id, {u'some': u'json'},
|
||||||
task=mock_create_task.return_value)
|
task=mock_create_task.return_value)
|
||||||
|
|
||||||
|
@mock.patch('rally.cmd.main.envutils.default_deployment_id')
|
||||||
|
def test_start_no_deploy_id(self, mock_default):
|
||||||
|
mock_default.side_effect = exceptions.InvalidArgumentsException
|
||||||
|
self.assertRaises(exceptions.InvalidArgumentsException,
|
||||||
|
self.task.start, 'path_to_config.json', None)
|
||||||
|
|
||||||
def test_abort(self):
|
def test_abort(self):
|
||||||
test_uuid = str(uuid.uuid4())
|
test_uuid = str(uuid.uuid4())
|
||||||
with mock.patch("rally.cmd.main.api") as mock_api:
|
with mock.patch("rally.cmd.main.api") as mock_api:
|
||||||
@@ -129,8 +137,64 @@ class DeploymentCommandsTestCase(test.BaseTestCase):
|
|||||||
self.deployment.recreate(deploy_id)
|
self.deployment.recreate(deploy_id)
|
||||||
mock_recreate.assert_called_once_with(deploy_id)
|
mock_recreate.assert_called_once_with(deploy_id)
|
||||||
|
|
||||||
|
@mock.patch('rally.cmd.main.envutils.default_deployment_id')
|
||||||
|
def test_recreate_no_deploy_id(self, mock_default):
|
||||||
|
mock_default.side_effect = exceptions.InvalidArgumentsException
|
||||||
|
self.assertRaises(exceptions.InvalidArgumentsException,
|
||||||
|
self.deployment.recreate, None)
|
||||||
|
|
||||||
@mock.patch('rally.cmd.main.api.destroy_deploy')
|
@mock.patch('rally.cmd.main.api.destroy_deploy')
|
||||||
def test_destroy(self, mock_destroy):
|
def test_destroy(self, mock_destroy):
|
||||||
deploy_id = str(uuid.uuid4())
|
deploy_id = str(uuid.uuid4())
|
||||||
self.deployment.destroy(deploy_id)
|
self.deployment.destroy(deploy_id)
|
||||||
mock_destroy.assert_called_once_with(deploy_id)
|
mock_destroy.assert_called_once_with(deploy_id)
|
||||||
|
|
||||||
|
@mock.patch('rally.cmd.main.envutils.default_deployment_id')
|
||||||
|
def test_destroy_no_deploy_id(self, mock_default):
|
||||||
|
mock_default.side_effect = exceptions.InvalidArgumentsException
|
||||||
|
self.assertRaises(exceptions.InvalidArgumentsException,
|
||||||
|
self.deployment.destroy, None)
|
||||||
|
|
||||||
|
@mock.patch('rally.cmd.main.db.deployment_get')
|
||||||
|
def test_config(self, mock_deployment):
|
||||||
|
deploy_id = str(uuid.uuid4())
|
||||||
|
value = {'config': 'config'}
|
||||||
|
mock_deployment.return_value = value
|
||||||
|
self.deployment.config(deploy_id)
|
||||||
|
mock_deployment.assert_called_once_with(deploy_id)
|
||||||
|
|
||||||
|
@mock.patch('rally.cmd.main.envutils.default_deployment_id')
|
||||||
|
def test_config_no_deploy_id(self, mock_default):
|
||||||
|
mock_default.side_effect = exceptions.InvalidArgumentsException
|
||||||
|
self.assertRaises(exceptions.InvalidArgumentsException,
|
||||||
|
self.deployment.config, None)
|
||||||
|
|
||||||
|
@mock.patch('rally.cmd.main.db.deployment_get')
|
||||||
|
def test_endpoint(self, mock_deployment):
|
||||||
|
deploy_id = str(uuid.uuid4())
|
||||||
|
value = {'endpoint': {}}
|
||||||
|
mock_deployment.return_value = value
|
||||||
|
self.deployment.endpoint(deploy_id)
|
||||||
|
mock_deployment.assert_called_once_with(deploy_id)
|
||||||
|
|
||||||
|
@mock.patch('rally.cmd.main.envutils.default_deployment_id')
|
||||||
|
def test_deploy_no_deploy_id(self, mock_default):
|
||||||
|
mock_default.side_effect = exceptions.InvalidArgumentsException
|
||||||
|
self.assertRaises(exceptions.InvalidArgumentsException,
|
||||||
|
self.deployment.endpoint, None)
|
||||||
|
|
||||||
|
|
||||||
|
class UseCommandsTestCase(test.BaseTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super(UseCommandsTestCase, self).setUp()
|
||||||
|
self.use = main.UseCommands()
|
||||||
|
|
||||||
|
@mock.patch('os.path.exists')
|
||||||
|
@mock.patch('rally.cmd.main.fileutils.update_env_file')
|
||||||
|
def test_deployment(self, mock_file, mock_path):
|
||||||
|
deploy_id = str(uuid.uuid4())
|
||||||
|
mock_path.return_value = True
|
||||||
|
self.use.deployment(deploy_id)
|
||||||
|
mock_path.assert_called_once_with(os.path.expanduser('~/.rally/'))
|
||||||
|
mock_file.assert_called_once_with(os.path.expanduser(
|
||||||
|
'~/.rally/deployment'), 'RALLY_DEPLOYMENT', deploy_id)
|
||||||
|
47
tests/test_fileutils.py
Normal file
47
tests/test_fileutils.py
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# Copyright 2013: Mirantis Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
|
||||||
|
from rally import fileutils
|
||||||
|
from tests import test
|
||||||
|
|
||||||
|
|
||||||
|
class FileUtilsTestCase(test.TestCase):
|
||||||
|
|
||||||
|
@mock.patch('os.path.exists')
|
||||||
|
@mock.patch.dict('os.environ', values={}, clear=True)
|
||||||
|
def test_load_env_vile(self, mock_path):
|
||||||
|
file_data = ["FAKE_ENV=fake_env\n"]
|
||||||
|
mock_path.return_value = True
|
||||||
|
with mock.patch('rally.fileutils.open', mock.mock_open(
|
||||||
|
read_data=file_data), create=True) as mock_file:
|
||||||
|
mock_file.return_value.readlines.return_value = file_data
|
||||||
|
fileutils.load_env_file('path_to_file')
|
||||||
|
self.assertIn('FAKE_ENV', os.environ)
|
||||||
|
mock_file.return_value.readlines.assert_called_once_with()
|
||||||
|
|
||||||
|
@mock.patch('os.path.exists')
|
||||||
|
def test_update_env_file(self, mock_path):
|
||||||
|
file_data = ["FAKE_ENV=old_value\n", "FAKE_ENV2=any\n"]
|
||||||
|
mock_path.return_value = True
|
||||||
|
with mock.patch('rally.fileutils.open', mock.mock_open(
|
||||||
|
read_data=file_data), create=True) as mock_file:
|
||||||
|
mock_file.return_value.readlines.return_value = file_data
|
||||||
|
fileutils.update_env_file('path_to_file', 'FAKE_ENV', 'new_value')
|
||||||
|
calls = [mock.call('FAKE_ENV2=any\n'), mock.call(
|
||||||
|
'FAKE_ENV=new_value')]
|
||||||
|
mock_file.return_value.readlines.assert_called_once_with()
|
||||||
|
mock_file.return_value.write.assert_has_calls(calls)
|
Reference in New Issue
Block a user