Skip to content

Commit

Permalink
Import shared code from ansiblelint (#5)
Browse files Browse the repository at this point in the history
This change should move all the shared code from ansiblelint and allow
removed of molecule on ansible-lint. Both with import the code from us.
  • Loading branch information
ssbarnea authored Jun 25, 2021
1 parent fb51303 commit e449cc6
Show file tree
Hide file tree
Showing 14 changed files with 897 additions and 6 deletions.
61 changes: 61 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
[flake8]

# Don't even try to analyze these:
exclude =
# No need to traverse egg files
*.egg,
# No need to traverse egg info dir
*.egg-info,
# No need to traverse eggs directory
.eggs,
# No need to traverse our git directory
.git,
# GitHub configs
.github,
# Cache files of MyPy
.mypy_cache,
# Cache files of pytest
.pytest_cache,
# Temp dir of pytest-testmon
.tmontmp,
# Countless third-party libs in venvs
.tox,
# Occasional virtualenv dir
.venv
# VS Code
.vscode,
# There's no value in checking cache directories
__pycache__,
# Temporary build dir
build,
# This contains sdists and wheels of ansible-lint that we don't want to check
dist,
# Occasional virtualenv dir
env,
# Metadata of `pip wheel` cmd is autogenerated
pip-wheel-metadata,

# Let's not overcomplicate the code:
max-complexity = 10

# Accessibility/large fonts and PEP8 friendly:
#max-line-length = 79
# Accessibility/large fonts and PEP8 unfriendly:
max-line-length = 100

# The only allowed ignores are related to black and isort
# https://black.readthedocs.io/en/stable/the_black_code_style.html#line-length
# "H" are generated by hacking plugin, which is not black compatible
ignore = E203,E501,W503,H

# Allow certain violations in certain files:
# per-file-ignores =

# flake8-pytest-style
# PT001:
pytest-fixture-no-parentheses = true
# PT006:
pytest-parametrize-names-type = tuple
# PT007:
pytest-parametrize-values-type = tuple
pytest-parametrize-values-row-type = tuple
16 changes: 13 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,24 @@ repos:
- flake8-docstrings>=1.5.0
- flake8-pytest-style>=1.2.2
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.902
rev: v0.910
hooks:
- id: mypy
# empty args needed in order to match mypy cli behavior
args: ["--strict"]
additional_dependencies: []
additional_dependencies:
- flaky
- packaging
- pytest
- tenacity
- types-PyYAML
- repo: https://github.com/pre-commit/mirrors-pylint
rev: v3.0.0a3
hooks:
- id: pylint
additional_dependencies: []
additional_dependencies:
- flaky
- pytest
- PyYAML
- tenacity
- typing_extensions
10 changes: 10 additions & 0 deletions .pylintrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
[BASIC]
good-names=f, # filename
i,
j,
k,
ns, # namespace
ex,
Run,
_

[IMPORTS]
preferred-modules =
unittest:pytest,
Expand Down
8 changes: 8 additions & 0 deletions constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ attrs==21.2.0
# via pytest
coverage==5.5
# via pytest-cov
flaky==3.7.0
# via ansible-compat (setup.py)
iniconfig==1.1.1
# via pytest
packaging==20.9
Expand All @@ -24,6 +26,12 @@ pytest==6.2.4
# via
# ansible-compat (setup.py)
# pytest-cov
pyyaml==5.4.1
# via ansible-compat (setup.py)
six==1.16.0
# via tenacity
tenacity==7.0.0
# via ansible-compat (setup.py)
toml==0.10.2
# via
# pytest
Expand Down
2 changes: 2 additions & 0 deletions examples/reqs_v1/requirements.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# v1 requirements test file
- src: geerlingguy.mysql
5 changes: 5 additions & 0 deletions examples/reqs_v2/requirements.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
roles:
- name: geerlingguy.mysql
collections:
- name: ssbarnea.molecule
10 changes: 10 additions & 0 deletions mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,15 @@ disallow_any_generics = True
; warn_unused_configs = True
exclude = test/local-content

[mypy-ansible.release]
ignore_missing_imports = True

[mypy-flaky]
# # https://github.com/box/flaky/issues/170
ignore_missing_imports = True

[mypy-pytest]
ignore_missing_imports = True

[mypy-setuptools]
ignore_missing_imports = True
5 changes: 4 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,13 @@ setup_requires =
setuptools_scm_git_archive>=1.0

# These are required in actual runtime:
; install_requires =
install_requires =
tenacity
PyYAML

[options.extras_require]
test =
flaky
pytest
pytest-cov

Expand Down
81 changes: 81 additions & 0 deletions src/ansible_compat/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
"""Store configuration options as a singleton."""
import os
import re
import subprocess
import sys
from functools import lru_cache
from typing import List, Optional, Tuple

from packaging.version import Version

from ansible_compat.constants import ANSIBLE_MISSING_RC

# Used to store collection list paths (with mock paths if needed)
collection_list: List[str] = []


@lru_cache()
def ansible_collections_path() -> str:
"""Return collection path variable for current version of Ansible."""
# respect Ansible behavior, which is to load old name if present
for env_var in ["ANSIBLE_COLLECTIONS_PATHS", "ANSIBLE_COLLECTIONS_PATH"]:
if env_var in os.environ:
return env_var

# https://github.com/ansible/ansible/pull/70007
if ansible_version() >= ansible_version("2.10.0.dev0"):
return "ANSIBLE_COLLECTIONS_PATH"
return "ANSIBLE_COLLECTIONS_PATHS"


def parse_ansible_version(stdout: str) -> Tuple[str, Optional[str]]:
"""Parse output of 'ansible --version'."""
# Ansible can produce extra output before displaying version in debug mode.

# ansible-core 2.11+: 'ansible [core 2.11.3]'
match = re.search(
r"^ansible \[(?:core|base) (?P<version>[^\]]+)\]", stdout, re.MULTILINE
)
if match:
return match.group("version"), None
# ansible-base 2.10 and Ansible 2.9: 'ansible 2.x.y'
match = re.search(r"^ansible (?P<version>[^\s]+)", stdout, re.MULTILINE)
if match:
return match.group("version"), None
return "", "FATAL: Unable parse ansible cli version: %s" % stdout


@lru_cache()
def ansible_version(version: str = "") -> Version:
"""Return current Version object for Ansible.
If version is not mentioned, it returns current version as detected.
When version argument is mentioned, it return converts the version string
to Version object in order to make it usable in comparisons.
"""
if version:
return Version(version)

proc = subprocess.run(
["ansible", "--version"],
universal_newlines=True,
check=False,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
if proc.returncode == 0:
version, error = parse_ansible_version(proc.stdout)
if error is not None:
print(error)
sys.exit(ANSIBLE_MISSING_RC)
else:
print(
"Unable to find a working copy of ansible executable.",
proc,
)
sys.exit(ANSIBLE_MISSING_RC)
return Version(version)


if ansible_collections_path() in os.environ:
collection_list = os.environ[ansible_collections_path()].split(':')
28 changes: 28 additions & 0 deletions src/ansible_compat/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""Constants used by ansible_compat."""


# Minimal version of Ansible we support for runtime
ANSIBLE_MIN_VERSION = "2.9"

# Based on https://docs.ansible.com/ansible/latest/reference_appendices/config.html
ANSIBLE_DEFAULT_ROLES_PATH = (
"~/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles"
)

INVALID_CONFIG_RC = 2
ANSIBLE_MISSING_RC = 4
INVALID_PREREQUISITES_RC = 10

MSG_INVALID_FQRL = """\
Computed fully qualified role name of %s does not follow current galaxy requirements.
Please edit meta/main.yml and assure we can correctly determine full role name:
galaxy_info:
role_name: my_name # if absent directory name hosting role is used instead
namespace: my_galaxy_namespace # if absent, author is used instead
Namespace: https://galaxy.ansible.com/docs/contributing/namespaces.html#galaxy-namespace-limitations
Role: https://galaxy.ansible.com/docs/contributing/creating_role.html#role-names
As an alternative, you can add 'role-name' to either skip_list or warn_list.
"""
10 changes: 10 additions & 0 deletions src/ansible_compat/loaders.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
"""Utilities for loading various files."""
from typing import Any

import yaml


def yaml_from_file(filepath: str) -> Any:
"""Return a loaded YAML file."""
with open(filepath) as content:
return yaml.load(content, Loader=yaml.FullLoader)
Loading

0 comments on commit e449cc6

Please sign in to comment.