Make ~/.tripleo/history owned by the correct user
When a tripleo subcommand command is executed with sudo, we identify the original user and create the history file in that user's home directory. When creating the file, we should make that user owns it, otherwise the user no longer able to run tripleo subcommends without sudo once the history file is created and owned by root. Change-Id: Ie6195b629fa65bcf9e5350f73d332e5034e8039b (cherry picked from commitbd70bcaa2c
) (cherry picked from commitd4b5576c39
)
This commit is contained in:
parent
b751bcdc38
commit
c945e677df
|
@ -15,8 +15,8 @@
|
|||
|
||||
|
||||
import ansible_runner
|
||||
import argparse
|
||||
import datetime
|
||||
import errno
|
||||
import fixtures
|
||||
import logging
|
||||
import mock
|
||||
|
@ -1355,34 +1355,65 @@ class TestGetSingleIp(TestCase):
|
|||
class TestStoreCliParam(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.args = argparse.ArgumentParser()
|
||||
class ArgsFake(object):
|
||||
def __init__(self):
|
||||
self.a = 1
|
||||
|
||||
self.args = ArgsFake()
|
||||
|
||||
@mock.patch('os.path.isdir')
|
||||
@mock.patch('os.path.exists')
|
||||
def test_exists_but_not_dir(self, mock_exists, mock_isdir):
|
||||
mock_exists.return_value = True
|
||||
@mock.patch('os.chown')
|
||||
@mock.patch('os.mkdir')
|
||||
def test_non_directory_exists(self, mock_mkdir, mock_chown, mock_isdir):
|
||||
mock_isdir.return_value = False
|
||||
self.assertRaises(exceptions.InvalidConfiguration,
|
||||
utils.store_cli_param,
|
||||
"overcloud deploy", self.args)
|
||||
|
||||
@mock.patch('tripleoclient.utils.datetime')
|
||||
@mock.patch('os.path.isdir')
|
||||
@mock.patch('os.path.exists')
|
||||
def test_write_cli_param(self, mock_exists, mock_isdir):
|
||||
@mock.patch('os.chown')
|
||||
@mock.patch('os.mkdir')
|
||||
def test_directory_exists(self, mock_mkdir, mock_chown, mock_isdir,
|
||||
mock_date):
|
||||
history_path = os.path.join(os.path.expanduser("~"), '.tripleo')
|
||||
mock_exists.return_value = True
|
||||
mock_mkdir.side_effect = OSError(errno.EEXIST, 'error')
|
||||
mock_isdir.return_value = True
|
||||
mock_file = mock.mock_open()
|
||||
mock_date.datetime.now.return_value = datetime.datetime(2017, 11, 22)
|
||||
|
||||
class ArgsFake(object):
|
||||
def __init__(self):
|
||||
self.a = 1
|
||||
|
||||
dt = datetime.datetime(2017, 11, 22)
|
||||
with mock.patch("builtins.open", mock_file):
|
||||
with mock.patch('tripleoclient.utils.datetime') as mock_date:
|
||||
mock_date.datetime.now.return_value = dt
|
||||
utils.store_cli_param("overcloud plan list", ArgsFake())
|
||||
utils.store_cli_param("overcloud plan list", self.args)
|
||||
|
||||
expected_call = [
|
||||
mock.call("%s/history" % history_path, 'a'),
|
||||
mock.call().write('2017-11-22 00:00:00 overcloud-plan-list a=1 \n')
|
||||
]
|
||||
mock_file.assert_has_calls(expected_call, any_order=True)
|
||||
|
||||
@mock.patch('os.path.isdir')
|
||||
@mock.patch('os.chown')
|
||||
@mock.patch('os.mkdir')
|
||||
def test_directory_fail(self, mock_mkdir, mock_chown, mock_isdir):
|
||||
mock_mkdir.side_effect = OSError()
|
||||
with self.assertRaises(IOError):
|
||||
utils.store_cli_param("overcloud plan list", self.args)
|
||||
mock_chown.assert_not_called()
|
||||
mock_isdir.assert_not_called()
|
||||
|
||||
@mock.patch('tripleoclient.utils.datetime')
|
||||
@mock.patch('os.path.isdir')
|
||||
@mock.patch('os.chown')
|
||||
@mock.patch('os.mkdir')
|
||||
def test_write_cli_param(self, mock_mkdir, mock_chown, mock_isdir,
|
||||
mock_date):
|
||||
history_path = os.path.join(os.path.expanduser("~"), '.tripleo')
|
||||
mock_isdir.return_value = True
|
||||
mock_file = mock.mock_open()
|
||||
mock_date.datetime.now.return_value = datetime.datetime(2017, 11, 22)
|
||||
|
||||
with mock.patch("builtins.open", mock_file):
|
||||
utils.store_cli_param("overcloud plan list", self.args)
|
||||
|
||||
expected_call = [
|
||||
mock.call("%s/history" % history_path, 'a'),
|
||||
|
@ -1392,12 +1423,14 @@ class TestStoreCliParam(TestCase):
|
|||
|
||||
@mock.patch('builtins.open')
|
||||
@mock.patch('os.path.isdir')
|
||||
@mock.patch('os.path.exists')
|
||||
def test_fail_to_write_data(self, mock_exists, mock_isdir, mock_open):
|
||||
mock_exists.return_value = True
|
||||
@mock.patch('os.chown')
|
||||
@mock.patch('os.mkdir')
|
||||
def test_fail_to_write_data(self, mock_mkdir, mock_chown, mock_isdir,
|
||||
mock_open):
|
||||
mock_isdir.return_value = True
|
||||
mock_open.side_effect = IOError()
|
||||
self.assertRaises(IOError, utils.store_cli_param, "command", self.args)
|
||||
with self.assertRaises(IOError):
|
||||
utils.store_cli_param("command", self.args)
|
||||
|
||||
|
||||
class ProcessMultipleEnvironments(TestCase):
|
||||
|
|
|
@ -863,16 +863,29 @@ def store_cli_param(command_name, parsed_args):
|
|||
command_name = command_name.replace(" ", "-")
|
||||
|
||||
history_path = os.path.join(constants.CLOUD_HOME_DIR, '.tripleo')
|
||||
makedirs(history_path)
|
||||
try:
|
||||
os.mkdir(history_path, 0o700)
|
||||
os.chown(history_path,
|
||||
int(os.environ.get('SUDO_UID', -1)),
|
||||
int(os.environ.get('SUDO_GID', -1)))
|
||||
except OSError as e:
|
||||
if e.errno != errno.EEXIST:
|
||||
messages = _("Unable to create the .tripleo directory: "
|
||||
"{0}, {1}").format(history_path, e)
|
||||
raise IOError(messages)
|
||||
|
||||
if os.path.isdir(history_path):
|
||||
try:
|
||||
with open(os.path.join(history_path,
|
||||
'history'), 'a') as history:
|
||||
history_file_path = os.path.join(history_path, 'history')
|
||||
with open(history_file_path, 'a') as history:
|
||||
args = parsed_args.__dict__.copy()
|
||||
used_args = ', '.join('%s=%s' % (key, value)
|
||||
for key, value in args.items())
|
||||
history.write(' '.join([str(datetime.datetime.now()),
|
||||
str(command_name), used_args, "\n"]))
|
||||
os.chown(history_file_path,
|
||||
int(os.environ.get('SUDO_UID', -1)),
|
||||
int(os.environ.get('SUDO_GID', -1)))
|
||||
except IOError as e:
|
||||
messages = _("Unable to write into TripleO history file: "
|
||||
"{0}, {1}").format(history_path, e)
|
||||
|
|
Loading…
Reference in New Issue