Merge "Add support for config reset command."
This commit is contained in:
commit
709af2e238
|
@ -16,6 +16,7 @@ import logging
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from kolla_cli.api.certificate import CertificateApi
|
from kolla_cli.api.certificate import CertificateApi
|
||||||
|
from kolla_cli.api.config import ConfigApi
|
||||||
from kolla_cli.api.control_plane import ControlPlaneApi
|
from kolla_cli.api.control_plane import ControlPlaneApi
|
||||||
from kolla_cli.api.group import GroupApi
|
from kolla_cli.api.group import GroupApi
|
||||||
from kolla_cli.api.host import HostApi
|
from kolla_cli.api.host import HostApi
|
||||||
|
@ -32,6 +33,7 @@ VERSION = '0.1'
|
||||||
|
|
||||||
class ClientApi(
|
class ClientApi(
|
||||||
CertificateApi,
|
CertificateApi,
|
||||||
|
ConfigApi,
|
||||||
ControlPlaneApi,
|
ControlPlaneApi,
|
||||||
GroupApi,
|
GroupApi,
|
||||||
HostApi,
|
HostApi,
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
# Copyright(c) 2018, Oracle and/or its affiliates. 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 kolla_cli.i18n as u
|
||||||
|
|
||||||
|
from kolla_cli.api.exceptions import FailedOperation
|
||||||
|
from kolla_cli.common import utils
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigApi(object):
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def config_reset():
|
||||||
|
"""Config Reset.
|
||||||
|
|
||||||
|
Resets the kolla-ansible configuration to its release defaults.
|
||||||
|
"""
|
||||||
|
actions_path = utils.get_kolla_actions_path()
|
||||||
|
cmd = ('%s config_reset' % actions_path)
|
||||||
|
err_msg, output = utils.run_cmd(cmd, print_output=False)
|
||||||
|
if err_msg:
|
||||||
|
raise FailedOperation(
|
||||||
|
u._('Configuration reset failed. {error} {message}')
|
||||||
|
.format(error=err_msg, message=output))
|
|
@ -0,0 +1,32 @@
|
||||||
|
# Copyright(c) 2018, Oracle and/or its affiliates. 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 logging
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
from cliff.command import Command
|
||||||
|
|
||||||
|
from kolla_cli.api.client import ClientApi
|
||||||
|
|
||||||
|
CLIENT = ClientApi()
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigReset(Command):
|
||||||
|
"""Resets the kolla-ansible configuration to its release defaults."""
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
try:
|
||||||
|
CLIENT.config_reset()
|
||||||
|
except Exception:
|
||||||
|
raise Exception(traceback.format_exc())
|
|
@ -29,6 +29,9 @@ from kolla_cli.api.exceptions import MissingArgument
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
private_key_string = 'private_key'
|
||||||
|
public_key_string = 'public_key'
|
||||||
|
|
||||||
|
|
||||||
def get_log_level():
|
def get_log_level():
|
||||||
evar = os.environ.get('KOLLA_LOG_LEVEL', 'info')
|
evar = os.environ.get('KOLLA_LOG_LEVEL', 'info')
|
||||||
|
@ -151,7 +154,7 @@ def run_cmd(cmd, print_output=True):
|
||||||
|
|
||||||
err = safe_decode(err)
|
err = safe_decode(err)
|
||||||
output = safe_decode(output)
|
output = safe_decode(output)
|
||||||
if process.returncode != 0:
|
if process is not None and process.returncode != 0:
|
||||||
err = (u._('Command failed. : {error}')
|
err = (u._('Command failed. : {error}')
|
||||||
.format(error=err))
|
.format(error=err))
|
||||||
if print_output:
|
if print_output:
|
||||||
|
@ -168,38 +171,97 @@ def change_password(file_path, pname, pvalue=None, public_key=None,
|
||||||
pvalue: value of password when not ssh key
|
pvalue: value of password when not ssh key
|
||||||
public_key: public ssh key
|
public_key: public ssh key
|
||||||
private_key: private ssh key
|
private_key: private ssh key
|
||||||
clear: flag to remove password
|
clear: flag to clear password
|
||||||
|
|
||||||
If clear, and password exists, remove it from the password file.
|
If key is not found, an error is returned.
|
||||||
If clear, and password doesn't exists, nothing is done.
|
If clear, and password exists, remove password.
|
||||||
If not clear, and key is not found, the new password will be added.
|
If clear, and password is already empty, nothing is done.
|
||||||
If not clear, and key is found, edit password in place.
|
If not clear, edit password in place.
|
||||||
|
|
||||||
The passwords file contains both key-value pairs and key-dictionary
|
The passwords file contains both key-value pairs and key-dictionary
|
||||||
pairs.
|
pairs. Type is maintained so you cannot change a key-dictionary
|
||||||
|
password to a key-value password or the other way around.
|
||||||
"""
|
"""
|
||||||
read_data = sync_read_file(file_path)
|
read_data = sync_read_file(file_path)
|
||||||
file_pwds = yaml.safe_load(read_data)
|
file_pwds = yaml.safe_load(read_data)
|
||||||
# if the password file is empty file_pwds will be None after safe_load
|
# if the password file is empty file_pwds will be None after safe_load
|
||||||
if file_pwds is None:
|
if file_pwds is None:
|
||||||
file_pwds = {}
|
file_pwds = {}
|
||||||
|
|
||||||
|
if pname not in file_pwds.keys():
|
||||||
|
raise Exception(
|
||||||
|
u._('unable to update password as it does not exist: {pname}')
|
||||||
|
.format(pname=pname))
|
||||||
|
|
||||||
|
ssh_password_type = is_ssh_password(file_pwds[pname])
|
||||||
|
|
||||||
if clear:
|
if clear:
|
||||||
# clear
|
# clear
|
||||||
if pname in file_pwds:
|
if pname in file_pwds:
|
||||||
del file_pwds[pname]
|
if ssh_password_type:
|
||||||
|
file_pwds[pname] = {private_key_string: None,
|
||||||
|
public_key_string: None}
|
||||||
|
else:
|
||||||
|
file_pwds[pname] = None
|
||||||
else:
|
else:
|
||||||
# edit
|
# edit
|
||||||
if private_key:
|
if private_key:
|
||||||
file_pwds[pname] = {'private_key': private_key,
|
if not ssh_password_type:
|
||||||
'public_key': public_key}
|
raise Exception(
|
||||||
|
u._('unable to set non ssh type password to ssh value'))
|
||||||
|
file_pwds[pname] = {private_key_string: private_key,
|
||||||
|
public_key_string: public_key}
|
||||||
else:
|
else:
|
||||||
|
if ssh_password_type:
|
||||||
|
raise Exception(
|
||||||
|
u._('unable to set ssh password type to non ssh value'))
|
||||||
if not pvalue:
|
if not pvalue:
|
||||||
pvalue = None
|
pvalue = None
|
||||||
file_pwds[pname] = pvalue
|
file_pwds[pname] = pvalue
|
||||||
write_data = yaml.safe_dump(file_pwds, default_flow_style=False)
|
|
||||||
|
# dump Nones as empty strings instead of the value 'null' as this is how
|
||||||
|
# it looks when we read it. also, this will not work with safe_dump
|
||||||
|
yaml.add_representer(type(None), _empty_is_none)
|
||||||
|
write_data = yaml.dump(file_pwds, default_flow_style=False)
|
||||||
sync_write_file(file_path, write_data)
|
sync_write_file(file_path, write_data)
|
||||||
|
|
||||||
|
|
||||||
|
def clear_all_passwords():
|
||||||
|
"""clear all passwords in passwords.yml file"""
|
||||||
|
password_path = os.path.join(get_kolla_etc(), 'passwords.yml')
|
||||||
|
read_data = sync_read_file(password_path)
|
||||||
|
file_pwds = yaml.safe_load(read_data)
|
||||||
|
# if the password file is empty file_pwds will be None after safe_load
|
||||||
|
if file_pwds is None:
|
||||||
|
file_pwds = {}
|
||||||
|
|
||||||
|
keys = file_pwds.keys()
|
||||||
|
for key in keys:
|
||||||
|
if is_ssh_password(file_pwds[key]):
|
||||||
|
file_pwds[key] = {private_key_string: None,
|
||||||
|
public_key_string: None}
|
||||||
|
else:
|
||||||
|
file_pwds[key] = None
|
||||||
|
|
||||||
|
yaml.add_representer(type(None), _empty_is_none)
|
||||||
|
write_data = yaml.dump(file_pwds, default_flow_style=False)
|
||||||
|
sync_write_file(password_path, write_data)
|
||||||
|
|
||||||
|
|
||||||
|
def _empty_is_none(self, _):
|
||||||
|
return self.represent_scalar('tag:yaml.org,2002:null', '')
|
||||||
|
|
||||||
|
|
||||||
|
def is_ssh_password(password):
|
||||||
|
if password is not None:
|
||||||
|
if isinstance(password, dict):
|
||||||
|
password_keys = password.keys()
|
||||||
|
if (private_key_string in password_keys and
|
||||||
|
public_key_string in password_keys):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def change_property(file_path, property_dict, clear=False):
|
def change_property(file_path, property_dict, clear=False):
|
||||||
"""change property with a file
|
"""change property with a file
|
||||||
|
|
||||||
|
|
|
@ -14,12 +14,6 @@ touch $KOLLA_ETC/kolla-cli/ansible/inventory.json
|
||||||
mkdir -p $KOLLA_HOME/kolla-cli
|
mkdir -p $KOLLA_HOME/kolla-cli
|
||||||
touch $KOLLA_HOME/kolla-cli/ansible.lock
|
touch $KOLLA_HOME/kolla-cli/ansible.lock
|
||||||
|
|
||||||
# setup kolla-ansible passwords file with just 2 passwords
|
|
||||||
cat > $KOLLA_ETC/passwords.yml <<EOF
|
|
||||||
database_password: foobar
|
|
||||||
nova_password: foobar
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# If it's not there, clone the kolla-ansible repo to get its ansible directory
|
# If it's not there, clone the kolla-ansible repo to get its ansible directory
|
||||||
# and then copy it over
|
# and then copy it over
|
||||||
mkdir -p $KOLLA_HOME/git
|
mkdir -p $KOLLA_HOME/git
|
||||||
|
@ -29,5 +23,6 @@ if [ ! -d $KOLLA_HOME/ansible ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# setup needed kolla-ansible files
|
# setup needed kolla-ansible files
|
||||||
|
cp $KOLLA_HOME/git/etc/kolla/passwords.yml $KOLLA_ETC/passwords.yml
|
||||||
mkdir -p $KOLLA_HOME/ansible/host_vars
|
mkdir -p $KOLLA_HOME/ansible/host_vars
|
||||||
touch $KOLLA_HOME/ansible/group_vars/__GLOBAL__
|
touch $KOLLA_HOME/ansible/group_vars/__GLOBAL__
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
# Copyright(c) 2016, Oracle and/or its affiliates. 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 kolla_cli.api.properties
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from kolla_cli.api.client import ClientApi
|
||||||
|
from kolla_cli.tests.functional.common import KollaCliTest
|
||||||
|
|
||||||
|
CLIENT = ClientApi()
|
||||||
|
|
||||||
|
|
||||||
|
class TestFunctional(KollaCliTest):
|
||||||
|
|
||||||
|
def test_config_reset(self):
|
||||||
|
# test global property reset
|
||||||
|
# set a property and make sure it was set correctly
|
||||||
|
property_dict = {'test': 'test'}
|
||||||
|
CLIENT.property_set(property_dict)
|
||||||
|
fetched_properties = CLIENT.property_get()
|
||||||
|
fetched_dict = self._properties_to_dict(fetched_properties)
|
||||||
|
self.assertIs(self._in_dict(property_dict, fetched_dict), True,
|
||||||
|
'property set failed')
|
||||||
|
|
||||||
|
# now clear the config and make sure the property we just
|
||||||
|
# set is now gone
|
||||||
|
CLIENT.config_reset()
|
||||||
|
fetched_properties = CLIENT.property_get()
|
||||||
|
fetched_dict = self._properties_to_dict(fetched_properties)
|
||||||
|
self.assertIs(self._in_dict(property_dict, fetched_dict), False,
|
||||||
|
'global property reset config failed')
|
||||||
|
|
||||||
|
# test host property reset
|
||||||
|
host_list = ['test']
|
||||||
|
CLIENT.host_add(host_list)
|
||||||
|
CLIENT.property_set(property_dict,
|
||||||
|
kolla_cli.api.properties.HOST_TYPE)
|
||||||
|
fetched_properties = CLIENT.property_get(
|
||||||
|
kolla_cli.api.properties.HOST_TYPE, host_list)
|
||||||
|
fetched_dict = self._properties_to_dict(fetched_properties)
|
||||||
|
self.assertIs(self._in_dict(property_dict, fetched_dict), True,
|
||||||
|
'host property set failed')
|
||||||
|
|
||||||
|
CLIENT.config_reset()
|
||||||
|
# need to add back in the host 'test' or the property
|
||||||
|
# get call will fail after a reset
|
||||||
|
CLIENT.host_add(host_list)
|
||||||
|
fetched_properties = CLIENT.property_get(
|
||||||
|
kolla_cli.api.properties.HOST_TYPE, host_list)
|
||||||
|
fetched_dict = self._properties_to_dict(fetched_properties)
|
||||||
|
self.assertIs(self._in_dict(property_dict, fetched_dict), False,
|
||||||
|
'host property reset config failed')
|
||||||
|
|
||||||
|
# test group property reset
|
||||||
|
group_list = ['control']
|
||||||
|
CLIENT.property_set(property_dict,
|
||||||
|
kolla_cli.api.properties.GROUP_TYPE)
|
||||||
|
fetched_properties = CLIENT.property_get(
|
||||||
|
kolla_cli.api.properties.GROUP_TYPE, group_list)
|
||||||
|
fetched_dict = self._properties_to_dict(fetched_properties)
|
||||||
|
self.assertIs(self._in_dict(property_dict, fetched_dict), True,
|
||||||
|
'group property set failed')
|
||||||
|
|
||||||
|
CLIENT.config_reset()
|
||||||
|
fetched_properties = CLIENT.property_get(
|
||||||
|
kolla_cli.api.properties.GROUP_TYPE, group_list)
|
||||||
|
fetched_dict = self._properties_to_dict(fetched_properties)
|
||||||
|
self.assertIs(self._in_dict(property_dict, fetched_dict), False,
|
||||||
|
'group property reset config failed')
|
||||||
|
|
||||||
|
# test host reset
|
||||||
|
# add a host and make sure it was added correctly
|
||||||
|
host_list = ['test']
|
||||||
|
CLIENT.host_add(host_list)
|
||||||
|
fetched_hosts = CLIENT.host_get_all()
|
||||||
|
fetched_list = self._hosts_to_list(fetched_hosts)
|
||||||
|
self.assertIs(set(host_list).issubset(fetched_list), True,
|
||||||
|
'host set failed')
|
||||||
|
|
||||||
|
# now clear the config and make sure the host we just
|
||||||
|
# added is now gone
|
||||||
|
CLIENT.config_reset()
|
||||||
|
fetched_hosts = CLIENT.host_get_all()
|
||||||
|
fetched_list = self._hosts_to_list(fetched_hosts)
|
||||||
|
self.assertIs(set(host_list).issubset(fetched_list), False,
|
||||||
|
'inventory reset config failed')
|
||||||
|
|
||||||
|
# need to populate the password file or many other tests will fail
|
||||||
|
CLIENT.password_init()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _properties_to_dict(props):
|
||||||
|
property_dict = {}
|
||||||
|
for prop in props:
|
||||||
|
property_dict[prop.name] = prop.value
|
||||||
|
return property_dict
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _hosts_to_list(hosts):
|
||||||
|
host_list = []
|
||||||
|
for host in hosts:
|
||||||
|
host_list.append(host.name)
|
||||||
|
return host_list
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _in_dict(base, target):
|
||||||
|
base_keys = base.keys()
|
||||||
|
target_keys = target.keys()
|
||||||
|
if set(base_keys).issubset(target_keys) is False:
|
||||||
|
return False
|
||||||
|
|
||||||
|
for key in base.keys():
|
||||||
|
target_value = target.get(key, None)
|
||||||
|
if target_value != base[key]:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
|
@ -12,12 +12,12 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
from kolla_cli.tests.functional.common import KollaCliTest
|
|
||||||
import os
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from kolla_cli.api import client
|
from kolla_cli.api import client
|
||||||
from kolla_cli.common.utils import get_kolla_etc
|
from kolla_cli.common.utils import get_kolla_etc
|
||||||
|
from kolla_cli.tests.functional.common import KollaCliTest
|
||||||
|
|
||||||
CLIENT = client.ClientApi()
|
CLIENT = client.ClientApi()
|
||||||
|
|
||||||
|
@ -54,13 +54,6 @@ PRIVATE_KEY = (
|
||||||
class TestFunctional(KollaCliTest):
|
class TestFunctional(KollaCliTest):
|
||||||
|
|
||||||
def test_password_set_clear(self):
|
def test_password_set_clear(self):
|
||||||
|
|
||||||
# This test should leave the passwords.yml file unchanged
|
|
||||||
# after the test completes. The tox setup bash script sets
|
|
||||||
# one password - "database_password" to "foobar".
|
|
||||||
pwds_path = os.path.join(get_kolla_etc(), 'passwords.yml')
|
|
||||||
size_start = os.path.getsize(pwds_path)
|
|
||||||
|
|
||||||
# test list
|
# test list
|
||||||
msg = self.run_cli_cmd('password list')
|
msg = self.run_cli_cmd('password list')
|
||||||
key = 'database_password'
|
key = 'database_password'
|
||||||
|
@ -69,26 +62,6 @@ class TestFunctional(KollaCliTest):
|
||||||
self.assertTrue(ok, 'list failed. Password (%s/%s) not in output: %s'
|
self.assertTrue(ok, 'list failed. Password (%s/%s) not in output: %s'
|
||||||
% (key, value, msg))
|
% (key, value, msg))
|
||||||
|
|
||||||
# test append
|
|
||||||
key = 'TeStKeY'
|
|
||||||
value = '-'
|
|
||||||
self.run_cli_cmd('password set %s --insecure %s' % (key, value))
|
|
||||||
msg = self.run_cli_cmd('password list')
|
|
||||||
ok = self._password_value_exists(key, value, msg)
|
|
||||||
self.assertTrue(ok, 'set new password failed. Password ' +
|
|
||||||
'(%s/%s) not in output: %s'
|
|
||||||
% (key, value, msg))
|
|
||||||
|
|
||||||
# test modify existing
|
|
||||||
key = 'TeStKeY'
|
|
||||||
value = '-'
|
|
||||||
self.run_cli_cmd('password set %s --insecure %s' % (key, value))
|
|
||||||
msg = self.run_cli_cmd('password list')
|
|
||||||
ok = self._password_value_exists(key, value, msg)
|
|
||||||
self.assertTrue(ok, 'set modify password failed. Password ' +
|
|
||||||
'(%s/%s) not in output: %s' %
|
|
||||||
(key, value, msg))
|
|
||||||
|
|
||||||
# test setting empty password
|
# test setting empty password
|
||||||
self.run_cli_cmd('password set %s --insecure' % key)
|
self.run_cli_cmd('password set %s --insecure' % key)
|
||||||
msg = self.run_cli_cmd('password list')
|
msg = self.run_cli_cmd('password list')
|
||||||
|
@ -106,28 +79,48 @@ class TestFunctional(KollaCliTest):
|
||||||
(key, msg))
|
(key, msg))
|
||||||
|
|
||||||
# test clear
|
# test clear
|
||||||
key = 'TeStKeY'
|
key = 'database_password'
|
||||||
value = '-'
|
value = '-'
|
||||||
self.run_cli_cmd('password clear %s' % key)
|
self.run_cli_cmd('password clear %s' % key)
|
||||||
msg = self.run_cli_cmd('password list')
|
msg = self.run_cli_cmd('password list')
|
||||||
ok = self._password_value_exists(key, value, msg)
|
ok = self._password_value_exists(key, value, msg)
|
||||||
self.assertFalse(ok, 'clear password failed. Password ' +
|
self.assertTrue(ok, 'clear password failed. Password ' +
|
||||||
'(%s/%s) not in output: %s' %
|
'(%s/%s) not in output: %s' %
|
||||||
(key, value, msg))
|
(key, value, msg))
|
||||||
|
|
||||||
# test setting/clearing an ssh key
|
# test setting an ssh key
|
||||||
key = 'TeStKeY'
|
key = 'nova_ssh_key'
|
||||||
CLIENT.password_set_sshkey(key, PRIVATE_KEY, PUBLIC_KEY)
|
CLIENT.password_set_sshkey(key, PRIVATE_KEY, PUBLIC_KEY)
|
||||||
keynames = CLIENT.password_get_names()
|
keynames = CLIENT.password_get_names()
|
||||||
self.assertIn(key, keynames, 'ssh key not in passwords')
|
self.assertIn(key, keynames, 'ssh key not in passwords')
|
||||||
CLIENT.password_clear(key)
|
|
||||||
keynames = CLIENT.password_get_names()
|
|
||||||
self.assertNotIn(key, keynames, 'ssh key not cleared from passwords')
|
|
||||||
|
|
||||||
# check that passwords.yml file size didn't change
|
# test modify non-ssh password
|
||||||
size_end = os.path.getsize(pwds_path)
|
key = 'database_password'
|
||||||
self.assertEqual(size_start, size_end, 'passwords.yml size changed ' +
|
value = '-'
|
||||||
'from %s to %s' % (size_start, size_end))
|
self.run_cli_cmd('password set %s --insecure %s' % (key, value))
|
||||||
|
msg = self.run_cli_cmd('password list')
|
||||||
|
ok = self._password_value_exists(key, value, msg)
|
||||||
|
self.assertTrue(ok, 'set modify password failed. Password ' +
|
||||||
|
'(%s/%s) not in output: %s' %
|
||||||
|
(key, value, msg))
|
||||||
|
|
||||||
|
# test to make sure that saves / loads aren't doing something
|
||||||
|
# bad to the password file size
|
||||||
|
CLIENT.password_clear(key)
|
||||||
|
# snapshot file size with key cleared
|
||||||
|
password_file_path = os.path.join(get_kolla_etc(), 'passwords.yml')
|
||||||
|
size_start = os.path.getsize(password_file_path)
|
||||||
|
# set and clear password
|
||||||
|
CLIENT.password_set(key, value)
|
||||||
|
CLIENT.password_clear(key)
|
||||||
|
size_end = os.path.getsize(password_file_path)
|
||||||
|
self.assertEqual(size_start, size_end, 'password file size changed ' +
|
||||||
|
'during set/clear (%s/%s)' % (size_start, size_end))
|
||||||
|
|
||||||
|
# make sure to end the test with the password init, as some other
|
||||||
|
# non-password related tests require that all passwords in the file
|
||||||
|
# be populated
|
||||||
|
CLIENT.password_init()
|
||||||
|
|
||||||
def _password_value_exists(self, key, value, cli_output):
|
def _password_value_exists(self, key, value, cli_output):
|
||||||
"""Verify cli data against model data"""
|
"""Verify cli data against model data"""
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
ansible>=1.9.2
|
ansible>=1.9.2
|
||||||
kolla-ansible
|
|
||||||
Babel>=0.9.6
|
Babel>=0.9.6
|
||||||
cliff>=1.13.0 # Apache-2.0
|
cliff>=1.13.0 # Apache-2.0
|
||||||
cliff-tablib<=1.1
|
cliff-tablib<=1.1
|
||||||
|
|
|
@ -29,6 +29,7 @@ console_scripts =
|
||||||
|
|
||||||
kolla.cli =
|
kolla.cli =
|
||||||
certificate_init = kolla_cli.commands.certificate:CertificateInit
|
certificate_init = kolla_cli.commands.certificate:CertificateInit
|
||||||
|
config_reset = kolla_cli.commands.config:ConfigReset
|
||||||
deploy = kolla_cli.commands.deploy:Deploy
|
deploy = kolla_cli.commands.deploy:Deploy
|
||||||
dump = kolla_cli.commands.support:Dump
|
dump = kolla_cli.commands.support:Dump
|
||||||
group_add = kolla_cli.commands.group:GroupAdd
|
group_add = kolla_cli.commands.group:GroupAdd
|
||||||
|
@ -61,6 +62,7 @@ kolla.cli =
|
||||||
setdeploy = kolla_cli.commands.deploy:Setdeploy
|
setdeploy = kolla_cli.commands.deploy:Setdeploy
|
||||||
upgrade = kolla_cli.commands.upgrade:Upgrade
|
upgrade = kolla_cli.commands.upgrade:Upgrade
|
||||||
|
|
||||||
|
|
||||||
[extract_messages]
|
[extract_messages]
|
||||||
keywords = _ gettext ngettext l_ lazy_gettext
|
keywords = _ gettext ngettext l_ lazy_gettext
|
||||||
mapping_file = babel.cfg
|
mapping_file = babel.cfg
|
||||||
|
|
|
@ -10,6 +10,7 @@ discover
|
||||||
fixtures>=0.3.14
|
fixtures>=0.3.14
|
||||||
mock>=1.0
|
mock>=1.0
|
||||||
mypy>=0.6; python_version>'2.7'
|
mypy>=0.6; python_version>'2.7'
|
||||||
|
oslo.utils>=3.33.0 # Apache-2.0
|
||||||
os-testr>=1.0.0 # Apache-2.0
|
os-testr>=1.0.0 # Apache-2.0
|
||||||
pexpect>=4.0.1
|
pexpect>=4.0.1
|
||||||
sphinx>=1.1.2,!=1.2.0,!=1.3b1,<1.3
|
sphinx>=1.1.2,!=1.2.0,!=1.3b1,<1.3
|
||||||
|
|
|
@ -20,10 +20,16 @@ import sys
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from kolla_cli.common.utils import change_password
|
from kolla_cli.common.utils import change_password
|
||||||
|
from kolla_cli.common.utils import clear_all_passwords
|
||||||
|
from kolla_cli.common.utils import get_kolla_ansible_home
|
||||||
|
from kolla_cli.common.utils import get_kolla_cli_etc
|
||||||
|
from kolla_cli.common.utils import get_kolla_etc
|
||||||
|
|
||||||
|
|
||||||
def _init_keys():
|
def _init_keys(path):
|
||||||
cmd = 'kolla-genpwd'
|
cmd = 'kolla-genpwd'
|
||||||
|
if os.path.exists(path):
|
||||||
|
cmd = ' '.join((cmd, '-p', path))
|
||||||
(_, err) = subprocess.Popen(cmd, shell=True,
|
(_, err) = subprocess.Popen(cmd, shell=True,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE).communicate()
|
stderr=subprocess.PIPE).communicate()
|
||||||
|
@ -117,7 +123,7 @@ def _password_cmd(argv):
|
||||||
init_flag = True
|
init_flag = True
|
||||||
if init_flag:
|
if init_flag:
|
||||||
# init empty keys
|
# init empty keys
|
||||||
_init_keys()
|
_init_keys(path)
|
||||||
elif list_flag:
|
elif list_flag:
|
||||||
# print the password keys
|
# print the password keys
|
||||||
_print_pwd_keys(path)
|
_print_pwd_keys(path)
|
||||||
|
@ -154,6 +160,56 @@ def _job_cmd(argv):
|
||||||
raise Exception('%s, pid %s' % (str(e), pid))
|
raise Exception('%s, pid %s' % (str(e), pid))
|
||||||
|
|
||||||
|
|
||||||
|
def _config_reset_cmd():
|
||||||
|
"""config_reset command
|
||||||
|
|
||||||
|
args for config_reset command
|
||||||
|
- none
|
||||||
|
"""
|
||||||
|
kolla_etc = get_kolla_etc()
|
||||||
|
kolla_home = get_kolla_ansible_home()
|
||||||
|
kollacli_etc = get_kolla_cli_etc()
|
||||||
|
|
||||||
|
group_vars_path = os.path.join(kolla_home, 'ansible/group_vars')
|
||||||
|
host_vars_path = os.path.join(kolla_home, 'ansible/host_vars')
|
||||||
|
globals_path = os.path.join(group_vars_path, '__GLOBAL__')
|
||||||
|
inventory_path = os.path.join(kollacli_etc, 'ansible/inventory.json')
|
||||||
|
|
||||||
|
# truncate global property and inventory files
|
||||||
|
with open(globals_path, 'w') as globals_file:
|
||||||
|
globals_file.truncate()
|
||||||
|
|
||||||
|
with open(inventory_path, 'w') as inventory_file:
|
||||||
|
inventory_file.truncate()
|
||||||
|
|
||||||
|
# clear all passwords
|
||||||
|
clear_all_passwords()
|
||||||
|
|
||||||
|
# nuke all files under the kolla etc base, skipping everything
|
||||||
|
# in the kollacli directory and the passwords.yml file
|
||||||
|
for dir_path, dir_names, file_names in os.walk(kolla_etc, topdown=False):
|
||||||
|
if 'kollacli' not in dir_path:
|
||||||
|
for dir_name in dir_names:
|
||||||
|
if dir_name != 'kollacli':
|
||||||
|
os.rmdir(os.path.join(dir_path, dir_name))
|
||||||
|
|
||||||
|
for file_name in file_names:
|
||||||
|
if file_name != 'passwords.yml':
|
||||||
|
os.remove(os.path.join(dir_path, file_name))
|
||||||
|
|
||||||
|
# nuke all property files under the kolla-ansible base other than
|
||||||
|
# all.yml and the global property file which we truncate above
|
||||||
|
for dir_path, _, file_names in os.walk(group_vars_path):
|
||||||
|
for file_name in file_names:
|
||||||
|
if (file_name != '__GLOBAL__' and
|
||||||
|
file_name != 'all.yml'):
|
||||||
|
os.remove(os.path.join(dir_path, file_name))
|
||||||
|
|
||||||
|
for dir_path, _, file_names in os.walk(host_vars_path):
|
||||||
|
for file_name in file_names:
|
||||||
|
os.remove(os.path.join(dir_path, file_name))
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""perform actions on behalf of kolla user
|
"""perform actions on behalf of kolla user
|
||||||
|
|
||||||
|
@ -163,6 +219,7 @@ def main():
|
||||||
Supported commands:
|
Supported commands:
|
||||||
- password
|
- password
|
||||||
- job
|
- job
|
||||||
|
- config_reset
|
||||||
"""
|
"""
|
||||||
if len(sys.argv) <= 1:
|
if len(sys.argv) <= 1:
|
||||||
raise Exception('Invalid number of parameters')
|
raise Exception('Invalid number of parameters')
|
||||||
|
@ -172,6 +229,8 @@ def main():
|
||||||
_password_cmd(sys.argv)
|
_password_cmd(sys.argv)
|
||||||
elif command == 'job':
|
elif command == 'job':
|
||||||
_job_cmd(sys.argv)
|
_job_cmd(sys.argv)
|
||||||
|
elif command == 'config_reset':
|
||||||
|
_config_reset_cmd()
|
||||||
else:
|
else:
|
||||||
raise Exception('Invalid command %s' % command)
|
raise Exception('Invalid command %s' % command)
|
||||||
|
|
||||||
|
|
8
tox.ini
8
tox.ini
|
@ -6,6 +6,7 @@ envlist = pep8,mypy,functional,functional-py35
|
||||||
[testenv]
|
[testenv]
|
||||||
usedevelop=True
|
usedevelop=True
|
||||||
whitelist_externals = find
|
whitelist_externals = find
|
||||||
|
bash
|
||||||
install_command = pip install -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages}
|
install_command = pip install -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages}
|
||||||
deps = -r{toxinidir}/requirements.txt
|
deps = -r{toxinidir}/requirements.txt
|
||||||
-r{toxinidir}/test-requirements.txt
|
-r{toxinidir}/test-requirements.txt
|
||||||
|
@ -22,12 +23,13 @@ whitelist_externals =
|
||||||
{toxinidir}/kolla_cli/tests/functional/functional_test_setup.sh
|
{toxinidir}/kolla_cli/tests/functional/functional_test_setup.sh
|
||||||
setenv =
|
setenv =
|
||||||
OS_TEST_PATH = ./kolla_cli/tests/functional
|
OS_TEST_PATH = ./kolla_cli/tests/functional
|
||||||
KOLLA_ETC = /tmp/kollaclitest/etc/kolla/
|
KOLLA_ETC = /tmp/kollaclitest/etc/kolla
|
||||||
KOLLA_HOME = /tmp/kollaclitest/usr/share/kolla-ansible/
|
KOLLA_HOME = /tmp/kollaclitest/usr/share/kolla-ansible
|
||||||
KOLLA_TOOLS_DIR = {toxinidir}/tools/
|
KOLLA_TOOLS_DIR = {toxinidir}/tools
|
||||||
commands =
|
commands =
|
||||||
{[testenv]commands}
|
{[testenv]commands}
|
||||||
{toxinidir}/kolla_cli/tests/functional/functional_test_setup.sh
|
{toxinidir}/kolla_cli/tests/functional/functional_test_setup.sh
|
||||||
|
bash -c "pushd /tmp/kollaclitest/usr/share/kolla-ansible/git; python setup.py install; popd"
|
||||||
ostestr {posargs} --serial
|
ostestr {posargs} --serial
|
||||||
|
|
||||||
[testenv:functional-py35]
|
[testenv:functional-py35]
|
||||||
|
|
Loading…
Reference in New Issue