diff --git a/zaza/__init__.py b/zaza/__init__.py index 5ffaf45..b113096 100644 --- a/zaza/__init__.py +++ b/zaza/__init__.py @@ -1,8 +1,9 @@ +"""Functions to support converting async function to a sync equivalent.""" import asyncio def run(*steps): - """Run the given steps in an asyncio loop + """Run the given steps in an asyncio loop. :returns: The result of the asyncio.Task :rtype: Any @@ -18,7 +19,7 @@ def run(*steps): def sync_wrapper(f): - """Convert the given async function into a sync function + """Convert the given async function into a sync function. :returns: The de-async'd function :rtype: function diff --git a/zaza/charm_tests/__init__.py b/zaza/charm_tests/__init__.py index e69de29..b2c4daa 100644 --- a/zaza/charm_tests/__init__.py +++ b/zaza/charm_tests/__init__.py @@ -0,0 +1 @@ +"""Collection of modules for testing a specific application.""" diff --git a/zaza/charm_tests/dragent/__init__.py b/zaza/charm_tests/dragent/__init__.py index e69de29..19b1452 100644 --- a/zaza/charm_tests/dragent/__init__.py +++ b/zaza/charm_tests/dragent/__init__.py @@ -0,0 +1 @@ +"""Collection of code for setting up and testing BGP.""" diff --git a/zaza/charm_tests/dragent/configure.py b/zaza/charm_tests/dragent/configure.py index 2091bfd..9cef2c2 100644 --- a/zaza/charm_tests/dragent/configure.py +++ b/zaza/charm_tests/dragent/configure.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +"""Setup for BGP deployments.""" from zaza.configure import ( network, @@ -42,7 +43,7 @@ DEFAULT_UNDERCLOUD_NETWORK_CONFIG = { def setup(): - """Setup BGP networking + """Run setup for BGP networking. Configure the following: The overcloud network using subnet pools @@ -54,7 +55,6 @@ def setup(): :returns: None :rtype: None """ - cli_utils.setup_logging() # Get network configuration settings diff --git a/zaza/charm_tests/dragent/test.py b/zaza/charm_tests/dragent/test.py index 28c766a..1c56c34 100644 --- a/zaza/charm_tests/dragent/test.py +++ b/zaza/charm_tests/dragent/test.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +"""Run BGP tests.""" import argparse import logging @@ -14,7 +15,7 @@ from zaza.utilities import ( def test_bgp_routes(peer_application_name="quagga", keystone_session=None): - """Test BGP routes + """Test BGP routes. :param peer_application_name: String name of BGP peer application :type peer_application_name: string @@ -24,7 +25,6 @@ def test_bgp_routes(peer_application_name="quagga", keystone_session=None): :returns: None :rtype: None """ - # If a session has not been provided, acquire one if not keystone_session: keystone_session = openstack_utils.get_overcloud_keystone_session() @@ -66,12 +66,11 @@ def test_bgp_routes(peer_application_name="quagga", keystone_session=None): def run_from_cli(): - """Run test for BGP routes from CLI + """Run test for BGP routes from CLI. :returns: None :rtype: None """ - cli_utils.setup_logging() parser = argparse.ArgumentParser() parser.add_argument("--peer-application", "-a", diff --git a/zaza/charm_tests/dragent/tests.py b/zaza/charm_tests/dragent/tests.py index 3d993c7..5e6957d 100644 --- a/zaza/charm_tests/dragent/tests.py +++ b/zaza/charm_tests/dragent/tests.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +"""Define class of BGP tests.""" import unittest @@ -7,14 +8,17 @@ from zaza.charm_tests.dragent import test class DRAgentTest(unittest.TestCase): + """Class to encapsulate BPG tests.""" BGP_PEER_APPLICATION = 'quagga' @classmethod def setUpClass(cls): + """Run setup for BGP tests.""" cli_utils.setup_logging() def test_bgp_routes(self): + """Run bgp tests.""" test.test_bgp_routes(peer_application_name=self.BGP_PEER_APPLICATION) diff --git a/zaza/charm_tests/glance/__init__.py b/zaza/charm_tests/glance/__init__.py index e69de29..cdb6914 100644 --- a/zaza/charm_tests/glance/__init__.py +++ b/zaza/charm_tests/glance/__init__.py @@ -0,0 +1 @@ +"""Collection of code for setting up and testing glance.""" diff --git a/zaza/charm_tests/glance/setup.py b/zaza/charm_tests/glance/setup.py index a7f0819..3216dbd 100644 --- a/zaza/charm_tests/glance/setup.py +++ b/zaza/charm_tests/glance/setup.py @@ -1,7 +1,10 @@ -#!/usr/bin/env python3 +"""Code for configuring glance.""" def basic_setup(): - """Glance setup for testing glance is currently part of glance functional - tests. Image setup for other tests to use should go here""" + """Run setup for testing glance. + + Glance setup for testing glance is currently part of glance functional + tests. Image setup for other tests to use should go here. + """ pass diff --git a/zaza/charm_tests/glance/tests.py b/zaza/charm_tests/glance/tests.py index 5861e12..76a6a4e 100644 --- a/zaza/charm_tests/glance/tests.py +++ b/zaza/charm_tests/glance/tests.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +"""Encapsulate glance testing.""" import logging @@ -7,15 +8,17 @@ import zaza.charm_tests.test_utils as test_utils class GlanceTest(test_utils.OpenStackBaseTest): + """Encapsulate glance tests.""" @classmethod def setUpClass(cls): + """Run class setup for running glance tests.""" super(GlanceTest, cls).setUpClass() cls.glance_client = openstack_utils.get_glance_session_client( cls.keystone_session) def test_410_glance_image_create_delete(self): - """Create an image and then delete it""" + """Create an image and then delete it.""" image_url = openstack_utils.find_cirros_image(arch='x86_64') image = openstack_utils.create_image( self.glance_client, @@ -24,8 +27,11 @@ class GlanceTest(test_utils.OpenStackBaseTest): openstack_utils.delete_image(self.glance_client, image.id) def test_411_set_disk_format(self): - """Change disk format and assert then change propagates to the correct - file and that services are restarted as a result""" + """Change disk format and check. + + Change disk format and assert then change propagates to the correct + file and that services are restarted as a result + """ # Expected default and alternate values set_default = { 'disk-formats': 'ami,ari,aki,vhd,vmdk,raw,qcow2,vdi,iso,root-tar'} @@ -47,6 +53,9 @@ class GlanceTest(test_utils.OpenStackBaseTest): ['glance-api']) def test_901_pause_resume(self): - """Pause service and check services are stopped then resume and check - they are started""" + """Run pause and resume tests. + + Pause service and check services are stopped then resume and check + they are started + """ self.pause_resume(['glance-api']) diff --git a/zaza/charm_tests/test_utils.py b/zaza/charm_tests/test_utils.py index 80860fd..4768ece 100644 --- a/zaza/charm_tests/test_utils.py +++ b/zaza/charm_tests/test_utils.py @@ -1,3 +1,4 @@ +"""Module containg base class for implementing charm tests.""" import logging import unittest import zaza.model @@ -8,6 +9,7 @@ import zaza.utilities.openstack as openstack_utils def skipIfNotHA(service_name): + """Run decorator to skip tests if application not in HA configuration.""" def _skipIfNotHA_inner_1(f): def _skipIfNotHA_inner_2(*args, **kwargs): ips = zaza.model.get_app_ips( @@ -23,10 +25,11 @@ def skipIfNotHA(service_name): class OpenStackBaseTest(unittest.TestCase): - """Generic helpers for testing OpenStack API charms""" + """Generic helpers for testing OpenStack API charms.""" @classmethod def setUpClass(cls): + """Run setup for test class to create common resourcea.""" cls.keystone_session = openstack_utils.get_overcloud_keystone_session() cls.model_name = model.get_juju_model() cls.test_config = lifecycle_utils.get_charm_config() @@ -38,8 +41,10 @@ class OpenStackBaseTest(unittest.TestCase): def restart_on_changed(self, config_file, default_config, alternate_config, default_entry, alternate_entry, services): - """Test that changing config results in config file being updates and - services restarted. Return config to default_config afterwards + """Run restart on change tests. + + Test that changing config results in config file being updates and + services restarted. Return config to default_config afterwards :param config_file: Config file to check for settings :type config_file: str @@ -114,8 +119,10 @@ class OpenStackBaseTest(unittest.TestCase): self.test_config.get('target_deploy_status', {})) def pause_resume(self, services): - """Pause and then resume a unit checking that services are in the - required state after each action + """Run Pause and resume tests. + + Pause and then resume a unit checking that services are in the + required state after each action :param services: Services expected to be restarted when config_file is changed. diff --git a/zaza/charm_tests/vault/__init__.py b/zaza/charm_tests/vault/__init__.py index e69de29..c9c701e 100644 --- a/zaza/charm_tests/vault/__init__.py +++ b/zaza/charm_tests/vault/__init__.py @@ -0,0 +1 @@ +"""Collection of code for setting up and testing vault.""" diff --git a/zaza/charm_tests/vault/setup.py b/zaza/charm_tests/vault/setup.py index 9db4de0..6fe8ce5 100644 --- a/zaza/charm_tests/vault/setup.py +++ b/zaza/charm_tests/vault/setup.py @@ -4,6 +4,7 @@ import zaza.charm_tests.vault.utils as vault_utils def basic_setup(): + """Run basic setup for vault tests.""" clients = vault_utils.get_clients() vip_client = vault_utils.get_vip_client() if vip_client: diff --git a/zaza/charm_tests/vault/tests.py b/zaza/charm_tests/vault/tests.py index 3b89eca..5307737 100644 --- a/zaza/charm_tests/vault/tests.py +++ b/zaza/charm_tests/vault/tests.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +"""Collection of tests for vault.""" import hvac import time @@ -15,9 +16,11 @@ import zaza.model class VaultTest(unittest.TestCase): + """Encapsulate vault tests.""" @classmethod def setUpClass(cls): + """Run setup for Vault tests.""" cls.clients = vault_utils.get_clients() cls.vip_client = vault_utils.get_vip_client() if cls.vip_client: @@ -27,6 +30,7 @@ class VaultTest(unittest.TestCase): vault_utils.auth_all(cls.clients, cls.vault_creds['root_token']) def test_csr(self): + """Test generating a csr and uploading a signed certificate.""" vault_actions = zaza.model.get_actions( 'vault') if 'get-csr' not in vault_actions: @@ -70,6 +74,7 @@ class VaultTest(unittest.TestCase): requests.get('https://{}:5000'.format(ip), verify=fp.name) def test_all_clients_authenticated(self): + """Check all vault clients are authenticated.""" for client in self.clients: for i in range(1, 10): try: @@ -82,12 +87,14 @@ class VaultTest(unittest.TestCase): self.assertTrue(client.hvac_client.is_authenticated()) def check_read(self, key, value): + """Check reading the key from all vault units.""" for client in self.clients: self.assertEqual( client.hvac_client.read('secret/uuids')['data']['uuid'], value) def test_consistent_read_write(self): + """Test reading and writing data to vault.""" key = 'secret/uuids' for client in self.clients: value = str(uuid.uuid1()) @@ -97,6 +104,7 @@ class VaultTest(unittest.TestCase): @test_utils.skipIfNotHA('vault') def test_vault_ha_statuses(self): + """Check Vault charm HA status.""" leader = [] leader_address = [] leader_cluster_address = [] @@ -116,11 +124,13 @@ class VaultTest(unittest.TestCase): self.assertEqual(len(set(leader_cluster_address)), 1) def test_check_vault_status(self): + """Check Vault charm status.""" for client in self.clients: self.assertFalse(client.hvac_client.seal_status['sealed']) self.assertTrue(client.hvac_client.seal_status['cluster_name']) def test_vault_authorize_charm_action(self): + """Test the authorize_charm action.""" vault_actions = zaza.model.get_actions( 'vault') if 'authorize-charm' not in vault_actions: diff --git a/zaza/charm_tests/vault/utils.py b/zaza/charm_tests/vault/utils.py index 9666c2b..a1f936b 100644 --- a/zaza/charm_tests/vault/utils.py +++ b/zaza/charm_tests/vault/utils.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +"""Module of functions for interfacing with vault and the vault charm.""" import base64 import hvac @@ -18,7 +19,7 @@ CharmVaultClient = collections.namedtuple( def get_unit_api_url(ip): - """Return URL for api access + """Return URL for api access. :param unit_ip: IP address to use in vault url :type unit_ip: str @@ -29,7 +30,7 @@ def get_unit_api_url(ip): def get_hvac_client(vault_url): - """Return an hvac client for the given URL + """Return an hvac client for the given URL. :param vault_url: Vault url to point client at :type vault_url: str @@ -40,7 +41,7 @@ def get_hvac_client(vault_url): def get_vip_client(): - """Return CharmVaultClient for the vip if a vip is being used + """Return CharmVaultClient for the vip if a vip is being used. :returns: CharmVaultClient :rtype: CharmVaultClient or None @@ -57,7 +58,7 @@ def get_vip_client(): def init_vault(client, shares=1, threshold=1): - """Initialise vault + """Initialise vault. :param client: Client to use for initiliasation :type client: CharmVaultClient @@ -72,7 +73,7 @@ def init_vault(client, shares=1, threshold=1): def get_clients(units=None): - """Create a list of clients, one per vault server + """Create a list of clients, one per vault server. :param units: List of IP addresses of vault endpoints :type units: [str, str, ...] @@ -92,7 +93,7 @@ def get_clients(units=None): def is_initialized(client): - """Check if vault is initialized + """Check if vault is initialized. :param client: Client to use to check if vault is initialized :type client: CharmVaultClient @@ -116,8 +117,10 @@ def is_initialized(client): def get_credentails(): - """Retrieve vault token and keys from unit. These are stored on a unit - during functional tests. + """Retrieve vault token and keys from unit. + + Retrieve vault token and keys from unit. These are stored on a unit + during functional tests. :returns: Tokens and keys for accessing test environment :rtype: dict @@ -135,8 +138,10 @@ def get_credentails(): def store_credentails(creds): - """Store the supplied credentials on a vault unit. ONLY USE FOR FUNCTIONAL - TESTING. + """Store the supplied credentials. + + Store the supplied credentials on a vault unit. ONLY USE FOR FUNCTIONAL + TESTING. :param creds: Keys and token to store :type creds: dict @@ -152,7 +157,7 @@ def store_credentails(creds): def get_credentails_from_file(auth_file): - """Read the vault credentials from the auth_file + """Read the vault credentials from the auth_file. :param auth_file: Path to file with credentials :type auth_file: str @@ -165,7 +170,7 @@ def get_credentails_from_file(auth_file): def write_credentails(auth_file, vault_creds): - """Write the vault credentials to the auth_file + """Write the vault credentials to the auth_file. :param auth_file: Path to file to write credentials :type auth_file: str @@ -175,7 +180,7 @@ def write_credentails(auth_file, vault_creds): def unseal_all(clients, key): - """Unseal all the vaults with the given clients with the provided key + """Unseal all the vaults with the given clients with the provided key. :param clients: List of clients :type clients: [CharmVaultClient, ...] @@ -188,7 +193,7 @@ def unseal_all(clients, key): def auth_all(clients, token): - """Authenticate all the given clients with the provided token + """Authenticate all the given clients with the provided token. :param clients: List of clients :type clients: [CharmVaultClient, ...] @@ -200,6 +205,16 @@ def auth_all(clients, token): def run_charm_authorize(token): + """Authorize charm to perfom certain actions. + + Run vault charm action to authorize the charm to perform a limited + set of calls against the vault API. + + :param token: Token to authorize action against vault. + :type token: str + :returns: Action object + :rtype: juju.action.Action + """ return zaza.model.run_action_on_leader( 'vault', 'authorize-charm', @@ -207,6 +222,13 @@ def run_charm_authorize(token): def run_get_csr(): + """Retrieve CSR from vault. + + Run vault charm action to retrieve CSR from vault. + + :returns: Action object + :rtype: juju.action.Action + """ return zaza.model.run_action_on_leader( 'vault', 'get-csr', @@ -214,6 +236,18 @@ def run_get_csr(): def run_upload_signed_csr(pem, root_ca, allowed_domains): + """Upload signed cert to vault. + + :param pem: Signed certificate text + :type pem: str + :param token: Root CA text. + :type token: str + :param allowed_domains: List of domains that may have certs issued from + certificate. + :type allowed_domains: list + :returns: Action object + :rtype: juju.action.Action + """ return zaza.model.run_action_on_leader( 'vault', 'upload-signed-csr', diff --git a/zaza/configure/__init__.py b/zaza/configure/__init__.py index e69de29..b36eaa0 100644 --- a/zaza/configure/__init__.py +++ b/zaza/configure/__init__.py @@ -0,0 +1 @@ +"""Module for configuring deployed applications.""" diff --git a/zaza/configure/bgp_speaker.py b/zaza/configure/bgp_speaker.py index 091c0da..f2fcc45 100755 --- a/zaza/configure/bgp_speaker.py +++ b/zaza/configure/bgp_speaker.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +"""Module to setup BGP speaker configuration.""" import argparse import logging @@ -16,7 +17,7 @@ FIP_TEST = "FIP TEST" def setup_bgp_speaker(peer_application_name, keystone_session=None): - """Setup BGP Speaker + """Perform BGP Speaker setup. :param peer_application_name: String name of BGP peer application :type peer_application_name: string @@ -84,12 +85,11 @@ def setup_bgp_speaker(peer_application_name, keystone_session=None): def run_from_cli(): - """Run BGP Speaker setup from CLI + """Run BGP Speaker setup from CLI. :returns: None :rtype: None """ - cli_utils.setup_logging() parser = argparse.ArgumentParser() parser.add_argument("--peer-application", "-a", diff --git a/zaza/configure/network.py b/zaza/configure/network.py index 8dc3e13..f461ca1 100755 --- a/zaza/configure/network.py +++ b/zaza/configure/network.py @@ -1,17 +1,6 @@ #!/usr/bin/env python3 -import argparse -import logging -import sys - -from zaza.utilities import ( - cli as cli_utils, - generic as generic_utils, - juju as juju_utils, - openstack as openstack_utils, -) - -"""Configure network +"""Configure network. For these network configuration functions there are two distinct sets of settings. There is the configuration of the overcloud's network, the network @@ -75,9 +64,20 @@ As a script from CLI with a YAML file of configuration: ./network toploogy_name -f network.yaml """ +import argparse +import logging +import sys + +from zaza.utilities import ( + cli as cli_utils, + generic as generic_utils, + juju as juju_utils, + openstack as openstack_utils, +) + def setup_sdn(network_config, keystone_session=None): - """Setup Software Defined Network + """Perform setup for Software Defined Network. :param network_config: Network configuration settings dictionary :type network_config: dict @@ -86,7 +86,6 @@ def setup_sdn(network_config, keystone_session=None): :returns: None :rtype: None """ - # If a session has not been provided, acquire one if not keystone_session: keystone_session = openstack_utils.get_overcloud_keystone_session() @@ -168,8 +167,9 @@ def setup_sdn(network_config, keystone_session=None): def setup_gateway_ext_port(network_config, keystone_session=None): - """Setup external port on Neutron Gateway. - For OpenStack on OpenStack scenarios + """Perform setup external port on Neutron Gateway. + + For OpenStack on OpenStack scenarios. :param network_config: Network configuration dictionary :type network_config: dict @@ -178,7 +178,6 @@ def setup_gateway_ext_port(network_config, keystone_session=None): :returns: None :rtype: None """ - # If a session has not been provided, acquire one if not keystone_session: keystone_session = openstack_utils.get_undercloud_keystone_session() @@ -204,7 +203,7 @@ def setup_gateway_ext_port(network_config, keystone_session=None): def run_from_cli(**kwargs): - """Run network configurations from CLI + """Run network configurations from CLI. Use a YAML file of network configuration settings to configure the overcloud network. YAML file of the form: @@ -225,7 +224,6 @@ def run_from_cli(**kwargs): :returns: None :rtype: None """ - cli_utils.setup_logging() parser = argparse.ArgumentParser() parser.add_argument("net_topology", diff --git a/zaza/controller.py b/zaza/controller.py index 928a56d..748c97c 100644 --- a/zaza/controller.py +++ b/zaza/controller.py @@ -1,15 +1,18 @@ +"""Module for interacting with a juju controller.""" + import logging from juju.controller import Controller from zaza import sync_wrapper async def async_add_model(model_name, config=None): - """Add a model to the current controller + """Add a model to the current controller. :param model_name: Name to give the new model. :type model_name: str :param config: Model configuration. - :type config: dict""" + :type config: dict + """ controller = Controller() await controller.connect() logging.debug("Adding model {}".format(model_name)) @@ -24,10 +27,11 @@ add_model = sync_wrapper(async_add_model) async def async_destroy_model(model_name): - """Remove a model from the current controller + """Remove a model from the current controller. :param model_name: Name of model to remove - :type model_name: str""" + :type model_name: str + """ controller = Controller() await controller.connect() logging.debug("Destroying model {}".format(model_name)) @@ -38,7 +42,7 @@ destroy_model = sync_wrapper(async_destroy_model) async def async_get_cloud(): - """Return the name of the current cloud + """Return the name of the current cloud. :returns: Name of cloud :rtype: str @@ -53,7 +57,7 @@ get_cloud = sync_wrapper(async_get_cloud) async def async_list_models(): - """Return a list of tha available clouds + """Return a list of tha available clouds. :returns: List of clouds :rtype: list