Added initial mypy / pep-484 type hinting support.

Jira-Issue: None
This commit is contained in:
Borne Mace 2016-07-20 11:57:41 -07:00
parent 75550c3f99
commit 694b2db531
13 changed files with 316 additions and 253 deletions

View File

@ -25,6 +25,7 @@ class AsyncApi(object):
def async_deploy(self, hostnames=[],
serial_flag=False, verbose_level=1):
# type: (List[str], bool, int) -> Job
"""Deploy.
Deploy containers to hosts.
@ -49,6 +50,7 @@ class AsyncApi(object):
return Job(ansible_job)
def async_upgrade(self, verbose_level=1):
# type: (int) -> Job
"""Upgrade.
:param verbose_level: the higher the number, the more verbose
@ -65,6 +67,7 @@ class AsyncApi(object):
def async_host_destroy(self, hostnames, destroy_type, verbose_level=1,
include_data=False):
# type: (List[str], str, int, bool) -> Job
"""Destroy Hosts.
Stops and removes all kolla related docker containers on the
@ -100,6 +103,7 @@ class AsyncApi(object):
return Job(ansible_job)
def async_host_precheck(self, hostnames, verbose_level=1):
# type: (List[str], int) -> Job
"""Check pre-deployment configuration of hosts.
Check if host is ready for a new deployment. This will fail if

View File

@ -61,12 +61,14 @@ class ClientApi(
self._configure_logging()
def get_version(self):
# type: () -> str
return VERSION
def base_call(self):
LOG.info('base call')
def enable_console_logging(self, level, enable=True):
# type: (int, bool) -> None
"""enable/disable console logging for the api
enable: True/False
@ -117,6 +119,7 @@ class ClientApi(
LOG = logging.getLogger(__name__)
def _get_kolla_log_file_size(self):
# type: () -> int
envvar = 'KOLLA_LOG_FILE_SIZE'
size_str = os.environ.get(envvar, '500000')
try:

View File

@ -24,6 +24,7 @@ LOG = logging.getLogger(__name__)
class DeployApi(object):
def deploy_set_mode(self, remote_mode):
# type: (bool) -> None
"""Set deploy mode.
Set deploy mode to either local or remote. Local indicates

View File

@ -21,116 +21,8 @@ from kollacli.common.utils import safe_decode
class GroupApi(object):
class Group(object):
def __init__(self, groupname, servicenames, hostnames):
self.name = groupname
self._servicenames = servicenames
self._hostnames = hostnames
def get_name(self):
"""Get name
:return: group name
:rtype: string
"""
return self.name
def get_services(self):
"""Get names of services associated with this group.
:return: service names
:rtype: list of strings
"""
return copy(self._servicenames)
def add_service(self, servicename):
"""Add service to group
:param servicename: name of the service to add to the group
:type servicename: string
"""
check_arg(servicename, u._('Service name'), str)
servicename = safe_decode(servicename)
inventory = Inventory.load()
inventory.validate_servicenames([servicename])
group_services = inventory.get_group_services()
self._servicenames = group_services[self.name]
if servicename not in self._servicenames:
# service not associated with group, add it
inventory.add_group_to_service(self.name, servicename)
self._servicenames.append(servicename)
Inventory.save(inventory)
def remove_service(self, servicename):
"""Remove service from group
:param servicename: name of the service to remove from the group
:type servicename: string
"""
check_arg(servicename, u._('Service name'), str)
servicename = safe_decode(servicename)
inventory = Inventory.load()
inventory.validate_servicenames([servicename])
group_services = inventory.get_group_services()
self._servicenames = group_services[self.name]
if servicename in self._servicenames:
# service is associated with group, remove it
inventory.remove_group_from_service(self.name, servicename)
self._servicenames.remove(servicename)
Inventory.save(inventory)
def get_hosts(self):
"""Get names of hosts associated with this group.
:return: host names
:rtype: list of strings
"""
return copy(self._hostnames)
def add_host(self, hostname):
"""Add host to group
:param hostname: name of the host to add to the group
:type hostname: string
"""
check_arg(hostname, u._('Host name'), str)
hostname = safe_decode(hostname)
inventory = Inventory.load()
inventory.validate_hostnames([hostname])
group = inventory.get_group(self.name)
self._hostnames = group.get_hostnames()
if hostname not in self._hostnames:
# host not associated with group, add it
inventory.add_host(hostname, self.name)
self._hostnames.append(hostname)
Inventory.save(inventory)
def remove_host(self, hostname):
"""Remove host from group
:param hostname: name of the host to remove from the group
:type hostname: string
"""
check_arg(hostname, u._('Host name'), str)
hostname = safe_decode(hostname)
inventory = Inventory.load()
inventory.validate_hostnames([hostname])
group = inventory.get_group(self.name)
self._hostnames = group.get_hostnames()
if hostname in self._hostnames:
# host is associated with group, remove it
inventory.remove_host(hostname, self.name)
self._hostnames.remove(hostname)
Inventory.save(inventory)
def group_add(self, groupnames):
# type: (List[str]) -> None
"""Add groups to the inventory
:param groupnames: names of the groups to add to the inventory
@ -146,6 +38,7 @@ class GroupApi(object):
Inventory.save(inventory)
def group_remove(self, groupnames):
# type: (List[str]) -> None
"""Remove groups from the inventory
:param groupnames: names of the groups to remove from the inventory
@ -160,6 +53,7 @@ class GroupApi(object):
Inventory.save(inventory)
def group_get_all(self):
# type: () -> List[Group]
"""Get all groups in the inventory
:return: groups
@ -168,6 +62,7 @@ class GroupApi(object):
return self._get_groups(None, get_all=True)
def group_get(self, groupnames):
# type: (List[str]) -> List[Group]
"""Get selected groups in the inventory
:param groupnames: names of groups to be read
@ -180,6 +75,7 @@ class GroupApi(object):
return self._get_groups(groupnames)
def _get_groups(self, groupnames, get_all=False):
# type: (List[str], bool) -> List[Group]
groups = []
inventory = Inventory.load()
if get_all:
@ -190,8 +86,126 @@ class GroupApi(object):
group_services = inventory.get_group_services()
for groupname in groupnames:
inv_group = inventory.get_group(groupname)
group = self.Group(groupname,
group_services[groupname],
inv_group.get_hostnames())
group = Group(groupname,
group_services[groupname],
inv_group.get_hostnames())
groups.append(group)
return groups
class Group(object):
def __init__(self, groupname, servicenames, hostnames):
# type: (str, List[str], List[str]) -> None
self.name = groupname
self._servicenames = servicenames
self._hostnames = hostnames
def get_name(self):
# type: () -> str
"""Get name
:return: group name
:rtype: string
"""
return self.name
def get_services(self):
# type: () -> List[str]
"""Get names of services associated with this group.
:return: service names
:rtype: list of strings
"""
return copy(self._servicenames)
def add_service(self, servicename):
# type: (str) -> None
"""Add service to group
:param servicename: name of the service to add to the group
:type servicename: string
"""
check_arg(servicename, u._('Service name'), str)
servicename = safe_decode(servicename)
inventory = Inventory.load()
inventory.validate_servicenames([servicename])
group_services = inventory.get_group_services()
self._servicenames = group_services[self.name]
if servicename not in self._servicenames:
# service not associated with group, add it
inventory.add_group_to_service(self.name, servicename)
self._servicenames.append(servicename)
Inventory.save(inventory)
def remove_service(self, servicename):
# type: (str) -> None
"""Remove service from group
:param servicename: name of the service to remove from the group
:type servicename: string
"""
check_arg(servicename, u._('Service name'), str)
servicename = safe_decode(servicename)
inventory = Inventory.load()
inventory.validate_servicenames([servicename])
group_services = inventory.get_group_services()
self._servicenames = group_services[self.name]
if servicename in self._servicenames:
# service is associated with group, remove it
inventory.remove_group_from_service(self.name, servicename)
self._servicenames.remove(servicename)
Inventory.save(inventory)
def get_hosts(self):
# type: () -> List[str]
"""Get names of hosts associated with this group.
:return: host names
:rtype: list of strings
"""
return copy(self._hostnames)
def add_host(self, hostname):
# type: (str) -> None
"""Add host to group
:param hostname: name of the host to add to the group
:type hostname: string
"""
check_arg(hostname, u._('Host name'), str)
hostname = safe_decode(hostname)
inventory = Inventory.load()
inventory.validate_hostnames([hostname])
group = inventory.get_group(self.name)
self._hostnames = group.get_hostnames()
if hostname not in self._hostnames:
# host not associated with group, add it
inventory.add_host(hostname, self.name)
self._hostnames.append(hostname)
Inventory.save(inventory)
def remove_host(self, hostname):
# type: (str) -> None
"""Remove host from group
:param hostname: name of the host to remove from the group
:type hostname: string
"""
check_arg(hostname, u._('Host name'), str)
hostname = safe_decode(hostname)
inventory = Inventory.load()
inventory.validate_hostnames([hostname])
group = inventory.get_group(self.name)
self._hostnames = group.get_hostnames()
if hostname in self._hostnames:
# host is associated with group, remove it
inventory.remove_host(hostname, self.name)
self._hostnames.remove(hostname)
Inventory.save(inventory)

View File

@ -21,33 +21,8 @@ from kollacli.common.utils import safe_decode
class HostApi(object):
class Host(object):
"""Host"""
def __init__(self, hostname, groupnames):
self.name = hostname
self._groupnames = groupnames
def get_name(self):
"""Get name
:return: host name
:rtype: string
"""
return self.name
def get_groups(self):
"""Get names of the groups associated with this host
:return: group names
:rtype: list of strings
Note: If the groups associated with this host change after this
host is fetched, the host must be re-fetched to reflect those
changes.
"""
return copy(self._groupnames)
def host_add(self, hostnames):
# type: (List[str]) -> None
"""Add hosts to the inventory
:param hostnames: list of strings
@ -65,6 +40,7 @@ class HostApi(object):
Inventory.save(inventory)
def host_remove(self, hostnames):
# type: (List[str]) -> None
"""Remove hosts from the inventory
:param hostnames: list of strings
@ -82,24 +58,26 @@ class HostApi(object):
Inventory.save(inventory)
def host_get_all(self):
# type: () -> List[Host]
"""Get all hosts in the inventory
:return: Hosts
:rtype: Host
:rtype: list of Host objects
"""
inventory = Inventory.load()
hosts = []
host_groups = inventory.get_host_groups()
for hostname, groupnames in host_groups.items():
hosts.append(self.Host(hostname, groupnames))
hosts.append(Host(hostname, groupnames))
return hosts
def host_get(self, hostnames):
# type: (List[str]) -> List[Host]
"""Get selected hosts in the inventory
:param hostnames: list of strings
:return: hosts
:rtype: Host
:rtype: list of Host objects
"""
check_arg(hostnames, u._('Host names'), list)
hostnames = safe_decode(hostnames)
@ -109,10 +87,11 @@ class HostApi(object):
hosts = []
host_groups = inventory.get_host_groups()
for hostname in hostnames:
hosts.append(self.Host(hostname, host_groups[hostname]))
hosts.append(Host(hostname, host_groups[hostname]))
return hosts
def host_ssh_check(self, hostnames):
# type: (List[str]) -> Dict[str,Dict[str,object]]
"""Check hosts for ssh connectivity
Check status is a dictionary of form:
@ -134,6 +113,7 @@ class HostApi(object):
return summary
def host_setup(self, hosts_info):
# type: (Dict[str,Dict[str,object]]) -> None
"""Setup multiple hosts for ssh access
hosts_info is a dictionary of form:
@ -151,3 +131,34 @@ class HostApi(object):
inventory = Inventory.load()
inventory.validate_hostnames(hosts_info.keys())
inventory.setup_hosts(hosts_info)
class Host(object):
"""Host"""
def __init__(self, hostname, groupnames):
# type: (str, List[str]) -> None
self.name = hostname
self._groupnames = groupnames
def get_name(self):
# type: () -> str
"""Get name
:return: host name
:rtype: string
"""
return self.name
def get_groups(self):
# type: () -> List[str]
"""Get names of the groups associated with this host
:return: group names
:rtype: list of strings
Note: If the groups associated with this host change after this
host is fetched, the host must be re-fetched to reflect those
changes.
"""
return copy(self._groupnames)

View File

@ -19,6 +19,7 @@ class Job(object):
self._ansible_job = ansible_job
def wait(self):
# type: () -> int
"""Wait for job to complete
:return: 0 if job succeeded, 1 if job failed
@ -27,6 +28,7 @@ class Job(object):
return self._ansible_job.wait()
def get_status(self):
# type: () -> int
"""Get status of job
:return: None: job is still running
@ -38,6 +40,7 @@ class Job(object):
return self._ansible_job.get_status()
def get_error_message(self):
# type: () -> str
"""Get error message
:return: if job failed, this will return the error message.
@ -46,6 +49,7 @@ class Job(object):
return self._ansible_job.get_error_message()
def get_console_output(self):
# type: () -> str
"""Get the console output from the job
:return: console output useful for debugging failed jobs.

View File

@ -22,6 +22,7 @@ from kollacli.common.utils import check_arg
class PasswordApi(object):
def password_set(self, name, value):
# type: (str, str) -> None
"""Set password
:param name: name of the password
@ -33,6 +34,7 @@ class PasswordApi(object):
set_password(name, value)
def password_clear(self, name):
# type: (str) -> None
"""Clear password
:param name: name of the password
@ -42,6 +44,7 @@ class PasswordApi(object):
clear_password(name)
def password_get_names(self):
# type: () -> List[str]
"""Get password names
:return: password names

View File

@ -30,41 +30,9 @@ PROP_TYPES = [GLOBAL_TYPE, GROUP_TYPE, HOST_TYPE]
class PropertyApi(object):
class Property(object):
"""Property
Members:
- name (str): key
- value (str): value
- file_name (str): name of file property is from
- overrides (bool): does the property override some other value
- orig_value (str): the value which is overridden or None
- target (str): group or host name for group or host properties
- prop_type (str): one of 'global', 'group' or 'host'
- ovr_global (bool): true if property is overridden at global level
- ovr_group (bool): true if property is overridden at group level
- ovr_host (bool): true if property is overridden at host level
"""
def __init__(self, ansible_property, override_flags):
self.name = ansible_property.name
self.value = ansible_property.value
self.file_name = ansible_property.file_name
self.overrides = ansible_property.overrides
self.orig_value = ansible_property.orig_value
self.target = ansible_property.target
self.prop_type = ansible_property.prop_type
if override_flags is not None:
self.ovr_global = override_flags.ovr_global
self.ovr_group = override_flags.ovr_group
self.ovr_host = override_flags.ovr_host
else:
self.ovr_global = False
self.ovr_group = False
self.ovr_host = False
def property_set(self, property_dict,
property_type=GLOBAL_TYPE, change_set=None):
# type: (Dict[str,str], str, List[str]) -> None
"""Set a property
:param property_dict: property dictionary containing key / values
@ -100,6 +68,7 @@ class PropertyApi(object):
def property_clear(self, property_list, property_type=GLOBAL_TYPE,
change_set=None):
# type: (List[str], str, List[str]) -> None
"""Clear a property
:param property_list: property list
@ -129,6 +98,7 @@ class PropertyApi(object):
ansible_properties.clear_host_property(property_list, change_set)
def property_get(self, property_type=GLOBAL_TYPE, get_set=None):
# type: (str, List[str]) -> List[Property]
"""Returns a list of Property objects
:param property_type: one of 'global', 'group', or 'host'
@ -144,7 +114,6 @@ class PropertyApi(object):
ansible_properties = AnsibleProperties()
property_list = []
result_list = []
if property_type == GLOBAL_TYPE:
property_list = ansible_properties.get_all_unique()
@ -156,7 +125,7 @@ class PropertyApi(object):
override_flags = ansible_properties.get_all_override_flags()
for prop in property_list:
result = self.Property(prop, override_flags.get(prop.name, None))
result = Property(prop, override_flags.get(prop.name, None))
result_list.append(result)
return result_list
@ -166,3 +135,38 @@ class PropertyApi(object):
raise InvalidArgument(u._('Property Type ({value} is not one of '
'global, group or host')
.format(value=property_type))
class Property(object):
"""Property
Members:
- name (str): key
- value (str): value
- file_name (str): name of file property is from
- overrides (bool): does the property override some other value
- orig_value (str): the value which is overridden or None
- target (str): group or host name for group or host properties
- prop_type (str): one of 'global', 'group' or 'host'
- ovr_global (bool): true if property is overridden at global level
- ovr_group (bool): true if property is overridden at group level
- ovr_host (bool): true if property is overridden at host level
"""
def __init__(self, ansible_property, override_flags):
self.name = ansible_property.name
self.value = ansible_property.value
self.file_name = ansible_property.file_name
self.overrides = ansible_property.overrides
self.orig_value = ansible_property.orig_value
self.target = ansible_property.target
self.prop_type = ansible_property.prop_type
if override_flags is not None:
self.ovr_global = override_flags.ovr_global
self.ovr_group = override_flags.ovr_group
self.ovr_host = override_flags.ovr_host
else:
self.ovr_global = False
self.ovr_group = False
self.ovr_host = False

View File

@ -21,68 +21,8 @@ from kollacli.common.utils import safe_decode
class ServiceApi(object):
class Service(object):
"""Service
A service is one of the services available in openstack-kolla.
For example, this would be how the murano services would be
represented:
- murano
- parentname: None
- childnames: [murano-api, murano-engine]
- murano-api
- parentname: murano
- childnames: []
- murano-engine
- parentname: murano
- childnames: []
"""
def __init__(self, servicename, parentname=None,
childnames=[], groupnames=[]):
self.name = servicename
self.parentname = parentname
self._childnames = childnames
self._groupnames = groupnames
def get_name(self):
"""Get name
:return: service name
:rtype: string
"""
return self.name
def get_parent(self):
"""Get name of parent service
:return: parent service name
:rtype: string
"""
return self.parentname
def get_children(self):
"""Get names of the child services associated with this service
:return: child names
:rtype: list of strings
"""
return copy(self._childnames)
def get_groups(self):
"""Get names of the groups associated with this service
:return: group names
:rtype: list of strings
Note: If the groups associated with this service change after this
service is fetched, the service must be re-fetched to reflect those
changes.
"""
return copy(self._groupnames)
def service_get_all(self):
# type: () -> List[Service]
"""Get all services in the inventory
:return: services
@ -91,6 +31,7 @@ class ServiceApi(object):
return self._get_services(None, get_all=True)
def service_get(self, servicenames):
# type: (List[str]) -> List[Service]
"""Get selected services in the inventory
:param servicenames: names of services to be read
@ -103,6 +44,7 @@ class ServiceApi(object):
return self._get_services(servicenames)
def _get_services(self, servicenames, get_all=False):
# type: (List[str], bool) -> List[Service]
services = []
inventory = Inventory.load()
@ -118,15 +60,83 @@ class ServiceApi(object):
for servicename in servicenames:
inv_service = inventory.get_service(servicename)
if inv_service:
service = self.Service(inv_service.name,
None,
inv_service.get_sub_servicenames(),
inv_service.get_groupnames())
service = Service(inv_service.name,
None,
inv_service.get_sub_servicenames(),
inv_service.get_groupnames())
else:
inv_subservice = inventory.get_sub_service(servicename)
service = self.Service(inv_subservice.name,
inv_subservice.get_parent_servicename(),
[],
inv_subservice.get_groupnames())
service = Service(inv_subservice.name,
inv_subservice.get_parent_servicename(),
[],
inv_subservice.get_groupnames())
services.append(service)
return services
class Service(object):
"""Service
A service is one of the services available in openstack-kolla.
For example, this would be how the murano services would be
represented:
- murano
- parentname: None
- childnames: [murano-api, murano-engine]
- murano-api
- parentname: murano
- childnames: []
- murano-engine
- parentname: murano
- childnames: []
"""
def __init__(self, servicename, parentname=None,
childnames=[], groupnames=[]):
# type: (str, str, List[str], List[str]) -> None
self.name = servicename
self.parentname = parentname
self._childnames = childnames
self._groupnames = groupnames
def get_name(self):
# type: () -> str
"""Get name
:return: service name
:rtype: string
"""
return self.name
def get_parent(self):
# type: () -> str
"""Get name of parent service
:return: parent service name
:rtype: string
"""
return self.parentname
def get_children(self):
# type: () -> List[str]
"""Get names of the child services associated with this service
:return: child names
:rtype: list of strings
"""
return copy(self._childnames)
def get_groups(self):
# type: () -> List[str]
"""Get names of the groups associated with this service
:return: group names
:rtype: list of strings
Note: If the groups associated with this service change after this
service is fetched, the service must be re-fetched to reflect those
changes.
"""
return copy(self._groupnames)

View File

@ -25,6 +25,7 @@ from kollacli.common.utils import safe_decode
class SupportApi(object):
def support_dump(self, dirpath):
# type: (str) -> str
"""Dumps configuration data for debugging.
Dumps most files in /etc/kolla and /usr/share/kolla into a
@ -45,6 +46,7 @@ class SupportApi(object):
return dumpfile_path
def support_get_logs(self, servicenames, hostname, dirpath):
# type: (List[str], str, str) -> None
"""get container logs
Fetch the container log files of services from the specified hosts.

View File

@ -37,12 +37,12 @@ class AnsiblePlaybook(object):
flush_cache = True
print_output = True
verbose_level = 0
hosts = None
groups = None
services = None
hosts = None # type: List[str]
groups = None # type: List[str]
services = None # type: List[str]
serial = False
deploy_id = None
inventory = None
deploy_id = None # type: str
inventory = None # type: Inventory
def run(self):
try:

View File

@ -93,4 +93,3 @@ def ssh_get_public_key():
with open(keyfile_path, "r") as public_key_file:
public_key = public_key_file.read()
return public_key
return None

10
tox.ini
View File

@ -1,7 +1,7 @@
[tox]
minversion = 1.6
skipsdist = True
envlist = py27,py34,pep8,pep8pi,bandit
envlist = py27,py34,pep8,pep8pi,bandit,mypy
[testenv]
usedevelop = True
@ -27,6 +27,14 @@ commands = flake8
[testenv:pep8pi]
commands = flake8 ./ansible_plugins/kolla_callback.py --ignore=H102
[testenv:mypy]
basepython = python3
skip_install = true
deps =
mypy-lang
commands =
mypy --py2 --silent-imports kollacli
[testenv:venv]
commands = {posargs}