diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 0000000000000000000000000000000000000000..fa73f4a433c2cdd232f90397421b1e6fcdd90f31 --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,22 @@ +trigger: +- master + +pool: + vmImage: 'ubuntu-18.04' + +steps: +- task: UsePythonVersion@0 + inputs: + versionSpec: '3.6' + +- script: python -m pip install --upgrade pip setuptools wheel + displayName: Install tools + +- script: pip install pydocstyle flake8 + displayName: Install dependencies + +- script: flake8 . + displayName: Run flake8 checks + +- script: pydocstyle . + displayName: Verify docstings diff --git a/plugins/module_utils/ansible_freeipa_module.py b/plugins/module_utils/ansible_freeipa_module.py index 9e3254a3cb50df626071e10039e9ef3b58ae02e2..7c2956281b7b461c485d4af593c4eff3b39ac25d 100644 --- a/plugins/module_utils/ansible_freeipa_module.py +++ b/plugins/module_utils/ansible_freeipa_module.py @@ -63,9 +63,7 @@ if six.PY3: def valid_creds(module, principal): # noqa - """ - Get valid credintials matching the princial, try GSSAPI first - """ + """Get valid credentials matching the princial, try GSSAPI first.""" if "KRB5CCNAME" in os.environ: ccache = os.environ["KRB5CCNAME"] module.debug('KRB5CCNAME set to %s' % ccache) @@ -103,9 +101,7 @@ def valid_creds(module, principal): # noqa def temp_kinit(principal, password): - """ - kinit with password using a temporary ccache - """ + """Kinit with password using a temporary ccache.""" if not password: raise RuntimeError("The password is not set") if not principal: @@ -123,9 +119,7 @@ def temp_kinit(principal, password): def temp_kdestroy(ccache_dir, ccache_name): - """ - Destroy temporary ticket and remove temporary ccache - """ + """Destroy temporary ticket and remove temporary ccache.""" if ccache_name is not None: run([paths.KDESTROY, '-c', ccache_name], raiseonerr=False) if ccache_dir is not None: @@ -134,7 +128,12 @@ def temp_kdestroy(ccache_dir, ccache_name): def api_connect(context=None): """ - Create environment, initialize api and connect to ldap2 + Initialize IPA API with the provided context. + + `context` can be any of: + * `server` (default) + * `ansible-freeipa` + * `cli_installer` """ env = Env() env._bootstrap() @@ -157,28 +156,24 @@ def api_connect(context=None): def api_command(module, command, name, args): - """ - Call ipa.Command - """ + """Call ipa.Command.""" return api.Command[command](name, **args) def api_command_no_name(module, command, args): - """ - Call ipa.Command without a name. - """ + """Call ipa.Command without a name.""" return api.Command[command](**args) def api_check_param(command, name): - """ - Return if param exists in command param list - """ + """Check if param exists in command param list.""" return name in api.Command[command].params def execute_api_command(module, principal, password, command, name, args): """ + Execute an API command. + Get KRB ticket if not already there, initialize api, connect, execute command and destroy ticket again if it has been created also. """ @@ -300,10 +295,7 @@ def api_get_realm(): def gen_add_del_lists(user_list, res_list): - """ - Generate the lists for the addition and removal of members using the - provided user and ipa settings - """ + """Generate the lists for the addition and removal of members.""" add_list = list(set(user_list or []) - set(res_list or [])) del_list = list(set(res_list or []) - set(user_list or [])) @@ -312,8 +304,9 @@ def gen_add_del_lists(user_list, res_list): def encode_certificate(cert): """ - Encode a certificate using base64 with also taking FreeIPA and Python - versions into account + Encode a certificate using base64. + + It also takes FreeIPA and Python versions into account. """ if isinstance(cert, (str, unicode, bytes)): encoded = base64.b64encode(cert) @@ -335,9 +328,7 @@ def is_valid_port(port): def is_ipv4_addr(ipaddr): - """ - Test if figen IP address is a valid IPv4 address - """ + """Test if given IP address is a valid IPv4 address.""" try: socket.inet_pton(socket.AF_INET, ipaddr) except socket.error: @@ -346,9 +337,7 @@ def is_ipv4_addr(ipaddr): def is_ipv6_addr(ipaddr): - """ - Test if figen IP address is a valid IPv6 address - """ + """Test if given IP address is a valid IPv6 address.""" try: socket.inet_pton(socket.AF_INET6, ipaddr) except socket.error: diff --git a/plugins/modules/ipadnsconfig.py b/plugins/modules/ipadnsconfig.py index 4c9cf2d71a4652737adcf678bfc486d8b97dc465..0d4aa8764fc2c9c1b6a97acf21fb24b2a8e2ef20 100644 --- a/plugins/modules/ipadnsconfig.py +++ b/plugins/modules/ipadnsconfig.py @@ -97,11 +97,10 @@ RETURN = """ """ from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_text from ansible.module_utils.ansible_freeipa_module import temp_kinit, \ - temp_kdestroy, valid_creds, api_connect, api_command, \ + temp_kdestroy, valid_creds, api_connect, \ api_command_no_name, compare_args_ipa, module_params_get, \ - gen_add_del_lists, is_ipv4_addr, is_ipv6_addr, ipalib_errors + is_ipv4_addr, is_ipv6_addr def find_dnsconfig(module): diff --git a/plugins/modules/ipagroup.py b/plugins/modules/ipagroup.py index 477c505185d0cfbe0b307110b2feaf1f04ee1775..10a611441894971643f42ef36ea271bb171656b7 100644 --- a/plugins/modules/ipagroup.py +++ b/plugins/modules/ipagroup.py @@ -221,7 +221,10 @@ def main(): # Get parameters # general - ipaadmin_principal = module_params_get(ansible_module, "ipaadmin_principal") + ipaadmin_principal = module_params_get( + ansible_module, + "ipaadmin_principal", + ) ipaadmin_password = module_params_get(ansible_module, "ipaadmin_password") names = module_params_get(ansible_module, "name") diff --git a/plugins/modules/ipahost.py b/plugins/modules/ipahost.py index 9b22f5bf69f0423df9084bc069c41d4bbf47f73d..42bd7e1faf6fbb1f6f246ae72a4c623839e88ee9 100644 --- a/plugins/modules/ipahost.py +++ b/plugins/modules/ipahost.py @@ -875,9 +875,11 @@ def main(): res_find_dnsrecord = find_dnsrecord(ansible_module, name) except ipalib_errors.NotFound as e: msg = str(e) - if ip_address is None and \ - ("DNS is not configured" in msg or \ - "DNS zone not found" in msg): + dns_not_configured = "DNS is not configured" in msg + dns_zone_not_found = "DNS zone not found" in msg + if ip_address is None and ( + dns_not_configured or dns_zone_not_found + ): # IP address(es) not given and no DNS support in IPA # -> Ignore failure # IP address(es) not given and DNS zone is not found diff --git a/plugins/modules/ipauser.py b/plugins/modules/ipauser.py index 73f16eff3edaf0d35770d414c5f2a6c42235a5d5..1867ea7be45313826e1caaf5e49df5f5527149cb 100644 --- a/plugins/modules/ipauser.py +++ b/plugins/modules/ipauser.py @@ -655,9 +655,9 @@ def check_parameters(module, state, action, def extend_emails(email, default_email_domain): if email is not None: - return [ "%s@%s" % (_email, default_email_domain) - if "@" not in _email else _email - for _email in email] + return ["%s@%s" % (_email, default_email_domain) + if "@" not in _email else _email + for _email in email] return email diff --git a/roles/ipaclient/action_plugins/ipaclient_get_otp.py b/roles/ipaclient/action_plugins/ipaclient_get_otp.py index b7e8056751a5ea3bc715b011c5cb66d907686aab..dcddc0aedcd97ae19921b8cac287e33f3b6f1545 100644 --- a/roles/ipaclient/action_plugins/ipaclient_get_otp.py +++ b/roles/ipaclient/action_plugins/ipaclient_get_otp.py @@ -33,9 +33,7 @@ from ansible.plugins.action import ActionBase def run_cmd(args, stdin=None): - """ - Execute an external command. - """ + """Execute an external command.""" p_in = None p_out = subprocess.PIPE p_err = subprocess.PIPE @@ -53,8 +51,10 @@ def run_cmd(args, stdin=None): def kinit_password(principal, password, ccache_name, config): """ - Perform kinit using principal/password, with the specified config file - and store the TGT in ccache_name. + Perform kinit using principal/password. + + It uses the specified config file to kinit and stores the TGT + in ccache_name. """ args = ["/usr/bin/kinit", principal, '-c', ccache_name] old_config = os.environ.get('KRB5_CONFIG') @@ -71,8 +71,10 @@ def kinit_password(principal, password, ccache_name, config): def kinit_keytab(principal, keytab, ccache_name, config): """ - Perform kinit using principal/keytab, with the specified config file - and store the TGT in ccache_name. + Perform kinit using principal/keytab. + + It uses the specified config file to kinit and stores the TGT + in ccache_name. """ if gssapi is None: raise ImportError("gssapi is not available") @@ -126,7 +128,7 @@ class ActionModule(ActionBase): def run(self, tmp=None, task_vars=None): """ - handler for credential cache transfer + Handle credential cache transfer. ipa* commands can either provide a password or a keytab file in order to authenticate on the managed node with Kerberos. @@ -142,7 +144,6 @@ class ActionModule(ActionBase): Then the IPA commands can use this credential cache file. """ - if task_vars is None: task_vars = dict() diff --git a/roles/ipaclient/files/py3test.py b/roles/ipaclient/files/py3test.py index d370b6870ab5a1be8e25ea7fd0abe4243f4fcd3d..6bf70ab588b48d69a82b624dd1053eb130e963e3 100644 --- a/roles/ipaclient/files/py3test.py +++ b/roles/ipaclient/files/py3test.py @@ -1,7 +1,7 @@ #!/usr/bin/python3 # Test ipaclient python3 binding -from ipaclient.install.client import SECURE_PATH +from ipaclient.install.client import SECURE_PATH # noqa: F401 # Check ipapython version to be >= 4.6 from ipapython.version import NUM_VERSION, VERSION diff --git a/roles/ipaclient/library/ipaclient_api.py b/roles/ipaclient/library/ipaclient_api.py index 5ce722a907718196d611f028af2641081e1200d2..865438f3e3e9425039bf33acd5409551a5bb666e 100644 --- a/roles/ipaclient/library/ipaclient_api.py +++ b/roles/ipaclient/library/ipaclient_api.py @@ -100,7 +100,6 @@ def main(): realm = module.params.get('realm') hostname = module.params.get('hostname') - servers = module.params.get('servers') debug = module.params.get('debug') host_principal = 'host/%s@%s' % (hostname, realm) diff --git a/roles/ipaclient/library/ipaclient_get_facts.py b/roles/ipaclient/library/ipaclient_get_facts.py index 1492199bf6a1e20a51c44d5434b1caf10ec8d219..003715efd3926c88437f99106daed5654150b976 100644 --- a/roles/ipaclient/library/ipaclient_get_facts.py +++ b/roles/ipaclient/library/ipaclient_get_facts.py @@ -13,7 +13,7 @@ from ansible.module_utils.basic import AnsibleModule # pylint: disable=unused-import try: - from ipalib import api + from ipalib import api # noqa: F401 except ImportError: HAS_IPALIB = False else: @@ -27,7 +27,7 @@ else: from ipapython import sysrestore try: - import ipaserver + import ipaserver # noqa: F401 except ImportError: HAS_IPASERVER = False else: @@ -41,7 +41,7 @@ VAR_LIB_PKI_TOMCAT = "/var/lib/pki/pki-tomcat" def is_ntpd_configured(): # ntpd is configured when sysrestore.state contains the line # [ntpd] - ntpd_conf_section = re.compile('^\s*\[ntpd\]\s*$') + ntpd_conf_section = re.compile(r'^\s*\[ntpd\]\s*$') try: with open(SERVER_SYSRESTORE_STATE) as f: @@ -56,7 +56,7 @@ def is_ntpd_configured(): def is_dns_configured(): # dns is configured when /etc/named.conf contains the line # dyndb "ipa" "/usr/lib64/bind/ldap.so" { - bind_conf_section = re.compile('^\s*dyndb\s+"ipa"\s+"[^"]+"\s+{$') + bind_conf_section = re.compile(r'^\s*dyndb\s+"ipa"\s+"[^"]+"\s+{$') try: with open(NAMED_CONF) as f: diff --git a/roles/ipaclient/library/ipaclient_get_otp.py b/roles/ipaclient/library/ipaclient_get_otp.py index 7ec67dda2d4bd91d6e5d931cbb359ff3a4411830..03e8b2b08cb18e80806bf7c12d1782835efdf9ff 100644 --- a/roles/ipaclient/library/ipaclient_get_otp.py +++ b/roles/ipaclient/library/ipaclient_get_otp.py @@ -135,8 +135,7 @@ if six.PY3: def get_host_diff(ipa_host, module_host): """ - Compares two dictionaries containing host attributes and builds a dict - of differences. + Build a dict with the differences from two host dicts. :param ipa_host: the host structure seen from IPA :param module_host: the target host structure seen from the module params @@ -164,7 +163,7 @@ def get_host_diff(ipa_host, module_host): def get_module_host(module): """ - Creates a structure representing the host information + Create a structure representing the host information. Reads the module parameters and builds the host structure as expected from the module @@ -189,7 +188,7 @@ def get_module_host(module): def ensure_host_present(module, api, ipahost): """ - Ensures that the host exists in IPA and has the same attributes. + Ensure host exists in IPA and has the same attributes. :param module: the ansible module :param api: IPA api handle @@ -246,7 +245,7 @@ def ensure_host_present(module, api, ipahost): def ensure_host_absent(module, api, host): """ - Ensures that the host does not exist in IPA + Ensure host does not exist in IPA. :param module: the ansible module :param api: the IPA API handle @@ -271,9 +270,7 @@ def ensure_host_absent(module, api, host): def main(): - """ - Main routine for the ansible module. - """ + module = AnsibleModule( argument_spec=dict( principal=dict(default='admin'), @@ -288,7 +285,6 @@ def main(): supports_check_mode=True, ) - principal = module.params.get('principal', 'admin') ccache = module.params.get('ccache') fqdn = unicode(module.params.get('fqdn')) state = module.params.get('state') diff --git a/roles/ipaclient/library/ipaclient_test.py b/roles/ipaclient/library/ipaclient_test.py index 8e1d11cf24d70967abf2fbc6da351f50d57274cb..d5d7f7187941dff8e34ad8d7ba5298eaf478ad8a 100644 --- a/roles/ipaclient/library/ipaclient_test.py +++ b/roles/ipaclient/library/ipaclient_test.py @@ -235,7 +235,6 @@ def is_client_configured(): :returns: boolean """ - return (os.path.isfile(paths.IPA_DEFAULT_CONF) and os.path.isfile(os.path.join(paths.IPA_CLIENT_SYSRESTORE, sysrestore.SYSRESTORE_STATEFILE))) @@ -243,11 +242,10 @@ def is_client_configured(): def get_ipa_conf(): """ - Return IPA configuration read from /etc/ipa/default.conf + Return IPA configuration read from `/etc/ipa/default.conf`. :returns: dict containing key,value """ - parser = RawConfigParser() parser.read(paths.IPA_DEFAULT_CONF) result = dict() diff --git a/roles/ipareplica/files/py3test.py b/roles/ipareplica/files/py3test.py index 8c60ded45310e55f903a564a5f8ba541fc136b7e..ffb009cd498fc5d17f346d4a7db9eb4327663fb7 100644 --- a/roles/ipareplica/files/py3test.py +++ b/roles/ipareplica/files/py3test.py @@ -2,9 +2,13 @@ # Test ipaerver python3 binding try: - from ipaserver.install.server.replicainstall import install_check + from ipaserver.install.server.replicainstall import ( # noqa: F401 + install_check, + ) except ImportError: - from ipaserver.install.server.replicainstall import promote_check + from ipaserver.install.server.replicainstall import ( # noqa: F401 + promote_check, + ) # Check ipapython version to be >= 4.6 from ipapython.version import NUM_VERSION, VERSION diff --git a/roles/ipaserver/files/py3test.py b/roles/ipaserver/files/py3test.py index 8f5c2d8516ea0f5bbe361c6b514e35b2833bfa63..701e342409ec1f13d17b5dcc5b4a83eb8d9695ac 100644 --- a/roles/ipaserver/files/py3test.py +++ b/roles/ipaserver/files/py3test.py @@ -1,7 +1,7 @@ #!/usr/bin/python3 # Test ipaerver python3 binding -from ipaserver.install.server.install import install_check +from ipaserver.install.server.install import install_check # noqa: F401 # Check ipapython version to be >= 4.6 from ipapython.version import NUM_VERSION, VERSION diff --git a/setup.cfg b/setup.cfg index b254a8e4bb5effd6b55ba7402715523a232cb46c..d87f6f06d4666a885b32bdfc3808c793dc4b5f4b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,3 +20,13 @@ data_files = /usr/share/ansible/roles/ipaclient = roles/ipaclient/* /usr/share/ansible/roles/ipaserver = roles/ipaserver/* /usr/share/ansible/roles/ipareplica = roles/ipareplica/* + +[flake8] +extend-ignore = E203 +per-file-ignores = + plugins/*:E402 + roles/*:E402 + +[pydocstyle] +inherit = false +ignore = D1,D212,D203