diff --git a/.copier-answers.yml b/.copier-answers.yml new file mode 100644 index 0000000..8a7de38 --- /dev/null +++ b/.copier-answers.yml @@ -0,0 +1,29 @@ +# Autogenerated. Do not edit this by hand, use `copier update`. +--- +_commit: 0.3.7 +_src_path: https://github.com/salt-extensions/salt-extension-copier +author: Salt Core Team +author_email: saltproject@vmware.com +coc_contact: '' +copyright_begin: 2023 +deploy_docs: rolling +docs_url: https://salt-extensions.github.io/saltext-zabbix/ +integration_name: Zabbix +license: apache +loaders: + - module + - returner + - state +max_salt_version: 3007 +no_saltext_namespace: false +package_name: zabbix +project_name: zabbix +python_requires: '3.8' +salt_version: '3006' +source_url: https://github.com/salt-extensions/saltext-zabbix +ssh_fixtures: false +summary: Salt Extension for interacting with Zabbix +test_containers: true +tracker_url: https://github.com/salt-extensions/saltext-zabbix/issues +url: https://github.com/salt-extensions/saltext-zabbix +workflows: org diff --git a/.coveragerc b/.coveragerc index 3139c4e..836c23c 100644 --- a/.coveragerc +++ b/.coveragerc @@ -36,7 +36,7 @@ ignore_errors = True [paths] source = - saltext/saltext_zabbix - src/saltext/saltext_zabbix + saltext/zabbix + src/saltext/zabbix testsuite = tests/ diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..879568e --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,11 @@ +### Description of Issue + + +### Setup +(Please provide relevant configs and/or SLS files (Be sure to remove sensitive info).) + +### Steps to Reproduce Issue +(Include debug logs if possible and relevant.) + +### Versions Report +(Provided by running `salt --versions-report`. Please also mention any differences in master/minion versions.) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..b232a42 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,48 @@ +--- +name: Bug report +about: Create a report to help us improve +title: "[BUG]" +labels: bug, needs-triage +assignees: '' + +--- + +**Description** +A clear and concise description of what the bug is. + +**Setup** +(Please provide relevant configs and/or SLS files (be sure to remove sensitive info. There is no general set-up of Salt.) + +Please be as specific as possible and give set-up details. + +- [ ] on-prem machine +- [ ] VM (Virtualbox, KVM, etc. please specify) +- [ ] VM running on a cloud service, please be explicit and add details +- [ ] container (Kubernetes, Docker, containerd, etc. please specify) +- [ ] or a combination, please be explicit +- [ ] jails if it is FreeBSD +- [ ] classic packaging +- [ ] onedir packaging +- [ ] used bootstrap to install + + +**Steps to Reproduce the behavior** +(Include debug logs if possible and relevant) + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Versions Report** +
salt --versions-report +(Provided by running salt --versions-report. Please also mention any differences in master/minion versions.) + +```yaml +PASTE HERE +``` +
+ +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..4cf0d28 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,14 @@ +blank_issues_enabled: true +contact_links: + - name: Salt Community Slack + url: https://saltstackcommunity.slack.com/ + about: Please ask and answer questions here. + - name: Salt-Users Forum + url: https://groups.google.com/forum/#!forum/salt-users + about: Please ask and answer questions here. + - name: Salt on LiberaChat + url: https://web.libera.chat/#salt + about: Please ask and answer questions here. + - name: Security vulnerabilities + email: saltproject-security.pdl@broadcom.com + about: Please report security vulnerabilities here. diff --git a/.github/ISSUE_TEMPLATE/docs.md b/.github/ISSUE_TEMPLATE/docs.md new file mode 100644 index 0000000..59af749 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/docs.md @@ -0,0 +1,23 @@ +--- +name: Docs +about: Issue related to Salt Documentation +title: "[DOCS]" +labels: documentation, needs-triage +assignees: '' + +--- + +**Description** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Suggested Fix** +What did you expect to see in the documentation that is missing or needs updating? + +**Type of documentation** +This could be module documentation or a guide. + +**Location or format of documentation** +Insert page URL if applicable. + +**Additional context** +Add any other context or screenshots here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..0e0a390 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: "[FEATURE REQUEST]" +labels: feature, needs-triage +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/tech-debt.md b/.github/ISSUE_TEMPLATE/tech-debt.md new file mode 100644 index 0000000..5a546c6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/tech-debt.md @@ -0,0 +1,13 @@ +--- +name: Tech Debt +about: Issue is related to tech debt. This includes compatibility changes for newer versions of software and OSes that salt interacts with. +title: "[TECH DEBT]" +labels: tech-debt +assignees: '' + +--- + +### Description of the tech debt to be addressed, include links and screenshots + +### Versions Report +(Provided by running `salt --versions-report`. Please also mention any differences in master/minion versions.) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..7d63a7c --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,24 @@ +### What does this PR do? + +### What issues does this PR fix or reference? +Fixes: + +### Previous Behavior +Remove this section if not relevant + +### New Behavior +Remove this section if not relevant + +### Merge requirements satisfied? +**[NOTICE] Bug fixes or features added to Salt require tests.** + +- [ ] Docs +- [ ] Changelog - https://docs.saltproject.io/en/master/topics/development/changelog.html +- [ ] Tests written/updated + +### Commits signed with GPG? +Yes/No + +Please review [Salt's Contributing Guide](https://docs.saltproject.io/en/master/topics/development/contributing.html) for best practices. + +See GitHub's [page on GPG signing](https://help.github.com/articles/signing-commits-using-gpg/) for more information about signing commits with GPG. diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index b466b04..47c40ed 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -1,11 +1,21 @@ name: Pull Request or Push -on: [push, pull_request] +on: + push: + branches: + - 'main' # Run on pushes to main + tags-ignore: + - '*' # Ignore pushes to tags + pull_request: jobs: - ci: + call_central_workflow: name: CI - uses: ./.github/workflows/ci.yml + uses: salt-extensions/central-artifacts/.github/workflows/ci.yml@main + with: + deploy-docs: true permissions: contents: write + id-token: write + pages: write pull-requests: read diff --git a/.github/workflows/tag.yml b/.github/workflows/tag.yml new file mode 100644 index 0000000..dab0796 --- /dev/null +++ b/.github/workflows/tag.yml @@ -0,0 +1,33 @@ +name: Tagged Releases + +on: + push: + tags: + - "v*" # Only tags starting with "v" for "v1.0.0", etc. + +jobs: + get_tag_version: + runs-on: ubuntu-latest + outputs: + version: ${{ steps.get_version.outputs.version }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Extract tag name + id: get_version + run: echo "version=$(echo ${GITHUB_REF#refs/tags/v})" >> $GITHUB_OUTPUT + + call_central_workflow: + needs: get_tag_version + uses: salt-extensions/central-artifacts/.github/workflows/ci.yml@main + with: + deploy-docs: true + release: true + version: ${{ needs.get_tag_version.outputs.version }} + permissions: + contents: write + id-token: write + pages: write + pull-requests: read + secrets: inherit diff --git a/.gitignore b/.gitignore index 47f827a..0a2bc24 100644 --- a/.gitignore +++ b/.gitignore @@ -129,7 +129,7 @@ dmypy.json .pyre/ # Ignore the setuptools_scm auto-generated version module -src/saltext/saltext_zabbix/version.py +src/saltext/zabbix/version.py # Ignore CI generated artifacts artifacts/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml old mode 100644 new mode 100755 index 266d746..8eca2b4 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ minimum_pre_commit_version: 2.4.0 repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.0.1 + rev: v4.6.0 hooks: - id: check-merge-conflict # Check for files that contain merge conflict strings. - id: trailing-whitespace # Trims trailing whitespace. @@ -25,7 +25,7 @@ repos: name: Check CLI examples on execution modules entry: python .pre-commit-hooks/check-cli-examples.py language: system - files: ^src/saltext/saltext_zabbix/modules/.*\.py$ + files: ^src/saltext/zabbix/modules/.*\.py$ - repo: local hooks: @@ -37,17 +37,17 @@ repos: - repo: https://github.com/s0undt3ch/salt-rewrite # Automatically rewrite code with known rules - rev: 1.3.3 + rev: 2.5.2 hooks: - id: salt-rewrite alias: rewrite-docstrings name: Salt extensions docstrings auto-fixes - files: ^src/saltext/saltext_zabbix/.*\.py$ + files: ^src/saltext/zabbix/.*\.py$ args: [--silent] - repo: https://github.com/s0undt3ch/salt-rewrite # Automatically rewrite code with known rules - rev: 1.3.3 + rev: 2.5.2 hooks: - id: salt-rewrite alias: rewrite-tests @@ -56,55 +56,52 @@ repos: args: [--silent, -E, fix_docstrings] - repo: https://github.com/asottile/pyupgrade - rev: v2.31.0 + rev: v3.15.2 hooks: - id: pyupgrade - name: Rewrite Code to be Py3.6+ + name: Rewrite Code to be Py3.8+ args: [ - --py36-plus + --py38-plus ] - exclude: src/saltext/saltext_zabbix/version.py + exclude: src/saltext/zabbix/version.py - - repo: https://github.com/asottile/reorder_python_imports - rev: v2.6.0 + - repo: https://github.com/PyCQA/isort + rev: 5.13.2 hooks: - - id: reorder-python-imports + - id: isort args: [ - --py3-plus, + --py 38, ] - exclude: src/saltext/saltext_zabbix/version.py + exclude: src/saltext/zabbix/(__init__|version).py - repo: https://github.com/psf/black - rev: 21.7b0 + rev: 24.2.0 hooks: - id: black args: [-l 100] - exclude: src/saltext/saltext_zabbix/version.py - additional_dependencies: - - click<8.1.0 + exclude: src/saltext/zabbix/version.py - - repo: https://github.com/asottile/blacken-docs - rev: v1.10.0 + - repo: https://github.com/adamchainz/blacken-docs + rev: 1.16.0 hooks: - id: blacken-docs args: [--skip-errors] - files: ^(docs/.*\.rst|src/saltext/saltext_zabbix/.*\.py)$ + files: ^(docs/.*\.rst|src/saltext/zabbix/.*\.py)$ additional_dependencies: - - black==21.7b0 - - click<8.1.0 + - black==24.2.0 # <---- Formatting ----------------------------------------------------------------------------- # ----- Security ------------------------------------------------------------------------------> - repo: https://github.com/PyCQA/bandit - rev: "1.7.0" + rev: 1.7.8 hooks: - id: bandit alias: bandit-salt name: Run bandit against the code base args: [--silent, -lll, --skip, B701] - exclude: src/saltext/saltext_zabbix/version.py + exclude: src/saltext/zabbix/version.py - repo: https://github.com/PyCQA/bandit - rev: "1.7.0" + rev: 1.7.8 hooks: - id: bandit alias: bandit-tests @@ -114,168 +111,29 @@ repos: # <---- Security ------------------------------------------------------------------------------- # ----- Code Analysis -------------------------------------------------------------------------> - # - repo: https://github.com/saltstack/mirrors-nox - # rev: v2021.6.12 - # hooks: - # - id: nox - # alias: lint-src - # name: Lint Source Code - # files: ^((setup|noxfile)|src/.*)\.py$ - # args: - # - -e - # - lint-code-pre-commit - # - -- + - repo: https://github.com/saltstack/mirrors-nox + rev: v2022.11.21 + hooks: + - id: nox + alias: lint-src + name: Lint Source Code + files: ^((setup|noxfile)|src/.*)\.py$ + require_serial: true + args: + - -e + - lint-code-pre-commit + - -- - repo: https://github.com/saltstack/mirrors-nox - rev: v2021.6.12 + rev: v2022.11.21 hooks: - id: nox alias: lint-tests name: Lint Tests files: ^tests/.*\.py$ + require_serial: true args: - -e - lint-tests-pre-commit - -- # <---- Code Analysis -------------------------------------------------------------------------- - - # ----- Static Test Requirements --------------------------------------------------------------> - - repo: https://github.com/saltstack/pip-tools-compile-impersonate - rev: '4.1' - hooks: - - id: pip-tools-compile - alias: compile-3.6-test-requirements - name: Py3.6 Test Requirements - files: ^requirements/tests.in$ - pass_filenames: false - args: - - -v - - --py-version=3.6 - - --platform=linux - - requirements/tests.in - - - id: pip-tools-compile - alias: compile-3.7-test-requirements - name: Py3.7 Test Requirements - files: ^requirements/tests.in$ - pass_filenames: false - args: - - -v - - --py-version=3.7 - - --platform=linux - - requirements/tests.in - - - id: pip-tools-compile - alias: compile-3.8-test-requirements - name: Py3.8 Test Requirements - files: ^requirements/tests.in$ - pass_filenames: false - args: - - -v - - --py-version=3.8 - - --platform=linux - - requirements/tests.in - - - id: pip-tools-compile - alias: compile-3.9-test-requirements - name: Py3.9 Test Requirements - files: ^requirements/tests.in$ - pass_filenames: false - args: - - -v - - --py-version=3.9 - - --platform=linux - - requirements/tests.in - # <---- Static Test Requirements --------------------------------------------------------------- - - # ----- Static Lint Requirements --------------------------------------------------------------> - - id: pip-tools-compile - alias: compile-3.6-test-requirements - name: Py3.6 Lint Requirements - files: ^requirements/lint.in$ - pass_filenames: false - args: - - -v - - --py-version=3.6 - - --platform=linux - - requirements/lint.in - - - id: pip-tools-compile - alias: compile-3.7-test-requirements - name: Py3.7 Lint Requirements - files: ^requirements/lint.in$ - pass_filenames: false - args: - - -v - - --py-version=3.7 - - --platform=linux - - requirements/lint.in - - - id: pip-tools-compile - alias: compile-3.8-test-requirements - name: Py3.8 Lint Requirements - files: ^requirements/lint.in$ - pass_filenames: false - args: - - -v - - --py-version=3.8 - - --platform=linux - - requirements/lint.in - - - id: pip-tools-compile - alias: compile-3.9-test-requirements - name: Py3.9 Lint Requirements - files: ^requirements/lint.in$ - pass_filenames: false - args: - - -v - - --py-version=3.9 - - --platform=linux - - requirements/lint.in - # <---- Static Lint Requirements --------------------------------------------------------------- - - # ----- Static Docs Requirements --------------------------------------------------------------> - - id: pip-tools-compile - alias: compile-3.6-test-requirements - name: Py3.6 Docs Requirements - files: ^requirements/docs.in$ - pass_filenames: false - args: - - -v - - --py-version=3.6 - - --platform=linux - - requirements/docs.in - - - id: pip-tools-compile - alias: compile-3.7-test-requirements - name: Py3.7 Docs Requirements - files: ^requirements/docs.in$ - pass_filenames: false - args: - - -v - - --py-version=3.7 - - --platform=linux - - requirements/docs.in - - - id: pip-tools-compile - alias: compile-3.8-test-requirements - name: Py3.8 Docs Requirements - files: ^requirements/docs.in$ - pass_filenames: false - args: - - -v - - --py-version=3.8 - - --platform=linux - - requirements/docs.in - - - id: pip-tools-compile - alias: compile-3.9-test-requirements - name: Py3.9 Docs Requirements - files: ^requirements/docs.in$ - pass_filenames: false - args: - - -v - - --py-version=3.9 - - --platform=linux - - requirements/docs.in - # <---- Static Docs Requirements --------------------------------------------------------------- diff --git a/.pre-commit-hooks/check-cli-examples.py b/.pre-commit-hooks/check-cli-examples.py index 441fdbe..be94242 100644 --- a/.pre-commit-hooks/check-cli-examples.py +++ b/.pre-commit-hooks/check-cli-examples.py @@ -4,7 +4,7 @@ import sys CODE_ROOT = pathlib.Path(__file__).resolve().parent.parent -EXECUTION_MODULES_PATH = CODE_ROOT / "src" / "saltext" / "saltext_zabbix" / "modules" +EXECUTION_MODULES_PATH = CODE_ROOT / "src" / "saltext" / "zabbix" / "modules" def check_cli_examples(files): diff --git a/.pre-commit-hooks/make-autodocs.py b/.pre-commit-hooks/make-autodocs.py index bcaf528..a7b76f7 100644 --- a/.pre-commit-hooks/make-autodocs.py +++ b/.pre-commit-hooks/make-autodocs.py @@ -1,57 +1,118 @@ +import ast +import os.path import subprocess -import sys -from enum import IntEnum from pathlib import Path - repo_path = Path(subprocess.check_output(["git", "rev-parse", "--show-toplevel"]).decode().strip()) -src_dir = repo_path / "src" / "saltext" / "saltext-zabbix" +src_dir = repo_path / "src" / "saltext" / "zabbix" doc_dir = repo_path / "docs" docs_by_kind = {} +changed_something = False + + +def _find_virtualname(path): + tree = ast.parse(path.read_text()) + for node in ast.walk(tree): + if isinstance(node, ast.Assign): + for target in node.targets: + if isinstance(target, ast.Name) and target.id == "__virtualname__": + if isinstance(node.value, ast.Str): + virtualname = node.value.s + break + else: + continue + break + else: + virtualname = path.with_suffix("").name + return virtualname + + +def write_module(rst_path, path, use_virtualname=True): + if use_virtualname: + virtualname = "``" + _find_virtualname(path) + "``" + else: + virtualname = make_import_path(path) + module_contents = f"""\ +{virtualname} +{'='*len(virtualname)} + +.. automodule:: {make_import_path(path)} + :members: +""" + if not rst_path.exists() or rst_path.read_text() != module_contents: + print(rst_path) + rst_path.write_text(module_contents) + return True + return False + + +def write_index(index_rst, import_paths, kind): + if kind == "utils": + header_text = "Utilities" + common_path = os.path.commonpath(tuple(x.replace(".", "/") for x in import_paths)).replace( + "/", "." + ) + if any(x == common_path for x in import_paths): + common_path = common_path[: common_path.rfind(".")] + else: + header_text = ( + "execution modules" if kind.lower() == "modules" else kind.rstrip("s") + " modules" + ) + common_path = import_paths[0][: import_paths[0].rfind(".")] + header = f"{'_'*len(header_text)}\n{header_text.title()}\n{'_'*len(header_text)}" + index_contents = f"""\ +.. all-saltext.zabbix.{kind}: + +{header} + +.. currentmodule:: {common_path} + +.. autosummary:: + :toctree: + +{chr(10).join(sorted(' '+p[len(common_path)+1:] for p in import_paths))} +""" + if not index_rst.exists() or index_rst.read_text() != index_contents: + print(index_rst) + index_rst.write_text(index_contents) + return True + return False def make_import_path(path): - return ".".join(path.with_suffix("").parts[-4:]) + if path.name == "__init__.py": + path = path.parent + return ".".join(path.relative_to(repo_path / "src").with_suffix("").parts) -for path in Path(__file__).parent.parent.joinpath("src/saltext/saltext-zabbix/").glob("*/*.py"): +for path in src_dir.glob("*/*.py"): if path.name != "__init__.py": kind = path.parent.name - docs_by_kind.setdefault(kind, set()).add(path) + if kind != "utils": + docs_by_kind.setdefault(kind, set()).add(path) + +# Utils can have subdirectories, treat them separately +for path in (src_dir / "utils").rglob("*.py"): + if path.name == "__init__.py" and not path.read_text(): + continue + docs_by_kind.setdefault("utils", set()).add(path) for kind in docs_by_kind: kind_path = doc_dir / "ref" / kind - all_rst = kind_path / "all.rst" + index_rst = kind_path / "index.rst" import_paths = [] for path in sorted(docs_by_kind[kind]): import_path = make_import_path(path) import_paths.append(import_path) - rst_path = kind_path.joinpath(import_path).with_suffix(".rst") - print(rst_path) + rst_path = kind_path / (import_path + ".rst") rst_path.parent.mkdir(parents=True, exist_ok=True) - rst_path.write_text( - f""" -{import_path} -{'='*len(import_path)} + change = write_module(rst_path, path, use_virtualname=kind != "utils") + changed_something = changed_something or change -.. automodule:: {import_path} - :members: -""" - ) + write_index(index_rst, import_paths, kind) - header_text = "execution" if kind.lower() == "modules" else kind.rstrip("s") + " modules" - header = f"{'_'*len(header_text)}\n{header_text.title()}\n{'_'*len(header_text)}" - - all_rst.write_text( - f""" -.. all-saltext.saltext-zabbix.{kind}: - -{header} -.. autosummary:: - :toctree: - -{chr(10).join(sorted(' '+p for p in import_paths))} -""" - ) +# Ensure pre-commit realizes we did something +if changed_something: + exit(2) diff --git a/.pylintrc b/.pylintrc old mode 100644 new mode 100755 index b8b733a..5692f3b --- a/.pylintrc +++ b/.pylintrc @@ -72,7 +72,7 @@ ignored-modules= # Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the # number of processors available to use, and will cap the count on Windows to # avoid hangs. -jobs=1 +jobs=0 # Control the amount of potential inferred values when inferring a single # object. This can help the performance when dealing with large functions or @@ -632,7 +632,28 @@ signature-mutators= # List of additional names supposed to be defined in builtins. Remember that # you should avoid defining new builtins when possible. -additional-builtins= +additional-builtins=__opts__, + __salt__, + __pillar__, + __grains__, + __context__, + __runner__, + __ret__, + __env__, + __low__, + __states__, + __lowstate__, + __running__, + __active_provider_name__, + __master_opts__, + __jid_event__, + __instance_id__, + __salt_system_encoding__, + __proxy__, + __serializers__, + __reg__, + __executors__, + __events__ # Tells whether unused global variables should be treated as a violation. allow-global-unused-variables=yes diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..aec3363 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,5 @@ +The changelog format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). + +This project uses [Semantic Versioning](https://semver.org/) - MAJOR.MINOR.PATCH + +# Changelog diff --git a/CODE-OF-CONDUCT.md b/CODE-OF-CONDUCT.md new file mode 100644 index 0000000..44d0ace --- /dev/null +++ b/CODE-OF-CONDUCT.md @@ -0,0 +1,127 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in Salt +Extension Modules for Zabbix project and our community a +harassment-free experience for everyone, regardless of age, body size, visible +or invisible disability, ethnicity, sex characteristics, gender identity and +expression, level of experience, education, socio-economic status, nationality, +personal appearance, race, religion, or sexual identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..bb18c3e --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,14 @@ +Thanks for your interest in contributing to the Salt Extension Modules for +Zabbix! We welcome any contribution, large or small - from +adding a new feature to fixing a single letter typo. + +This is a companion to the Salt Project and the [Salt Contributing +Guide][salt-contributing] should be considered the default for this project. +Where this project disagrees with the Salt Project, the guidelines here take +precedence. Where this project is silent, the Salt guidelines should be used. + +See the **Contributing** section in the [README][README.md] for a quickstart. + + +[README.md]: README.md +[salt-contributing]: https://docs.saltproject.io/en/master/topics/development/contributing.html diff --git a/LICENSE b/LICENSE index 844145d..b27fe9d 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2023 Salt Project + Copyright 2023 Salt Core Team Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..b77370e --- /dev/null +++ b/NOTICE @@ -0,0 +1,10 @@ +Salt Extension Modules for Zabbix +Copyright 2023 Salt Core Team + +This product is licensed to you under the Apache 2.0 license (the "License"). +You may not use this product except in compliance with the Apache 2.0 License. + +This product may include a number of subcomponents with separate copyright +notices and license terms. Your use of these subcomponents is subject to the +terms and conditions of the subcomponent's license, as noted in the LICENSE +file. diff --git a/README.md b/README.md index 7d7b445..dc38de0 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,87 @@ -# saltext-zabbix +# Salt Extension for Zabbix -Salt Extension Modules for interacting with Zabbix +Salt Extension for interacting with Zabbix -## Quickstart +## Security -To get started with your new project: +If you think you have found a security vulnerability, see +[Salt's security guide][security]. - # Create a new venv - python3 -m venv env --prompt saltext-zabbix - source env/bin/activate +## User Documentation - # On mac, you may need to upgrade pip - python -m pip install --upgrade pip +This README is for people aiming to contribute to the project. +If you just want to get started with the extension, check out the +[User Documentation][docs]. - # On WSL or some flavors of linux you may need to install the `enchant` - # library in order to build the docs - sudo apt-get install -y enchant +## Contributing - # Install extension + test/dev/doc dependencies into your environment - python -m pip install -e .[tests,dev,docs] +The saltext-zabbix project team welcomes contributions from the community. - # Run tests! - python -m nox -e tests-3 +The [Salt Contributing guide][salt-contributing] has a lot of relevant +information, but if you'd like to jump right in here's how to get started: - # skip requirements install for next time - export SKIP_REQUIREMENTS_INSTALL=1 - # Build the docs, serve, and view in your web browser: - python -m nox -e docs && (cd docs/_build/html; python -m webbrowser localhost:8000; python -m http.server; cd -) +```bash +# Clone the repo +git clone --origin salt git@github.com:salt-extensions/saltext-zabbix.git - # Run the example function - salt-call --local saltext-zabbix.example_function text="Happy Hacking!" +# Change to the repo dir +cd saltext-zabbix + +# Create a new venv +python3 -m venv env --prompt saltext-zabbix +source env/bin/activate + +# On mac, you may need to upgrade pip +python -m pip install --upgrade pip + +# On WSL or some flavors of linux you may need to install the `enchant` +# library in order to build the docs +sudo apt-get install -y enchant + +# Install extension + test/dev/doc dependencies into your environment +python -m pip install -e '.[tests,dev,docs]' + +# Run tests! +python -m nox -e tests-3 + +# skip requirements install for next time +export SKIP_REQUIREMENTS_INSTALL=1 + +# Build the docs, serve, and view in your web browser: +python -m nox -e docs && (cd docs/_build/html; python -m webbrowser localhost:8000; python -m http.server; cd -) +``` + +Writing code isn't the only way to contribute! We value contributions in any of +these areas: + +* Documentation - especially examples of how to use this module to solve + specific problems. +* Triaging [issues][issues] and participating in [discussions][discussions] +* Reviewing [Pull Requests][PRs] (we really like + [Conventional Comments][comments]!) + +You could also contribute in other ways: + +* Writing blog posts +* Posting on social media about how you used Salt + Zabbix to solve your + problems, including videos +* Giving talks at conferences +* Publishing videos +* Asking/answering questions in IRC, Discord or email groups + +Any of these things are super valuable to our community, and we sincerely +appreciate every contribution! + + +For more information, build the docs and head over to http://localhost:8000/ — +that's where you'll find the rest of the documentation. + + +[security]: https://github.com/saltstack/salt/blob/master/SECURITY.md +[salt-contributing]: https://docs.saltproject.io/en/master/topics/development/contributing.html +[issues]: https://github.com/salt-extensions/saltext-zabbix/issues +[PRs]: https://github.com/salt-extensions/saltext-zabbix/pulls +[discussions]: https://github.com/salt-extensions/saltext-zabbix/discussions +[comments]: https://conventionalcomments.org/ +[docs]: https://salt-extensions.github.io/saltext-zabbix/ diff --git a/changelog/.template.jinja b/changelog/.template.jinja new file mode 100644 index 0000000..0cf429a --- /dev/null +++ b/changelog/.template.jinja @@ -0,0 +1,15 @@ +{% if sections[""] %} +{% for category, val in definitions.items() if category in sections[""] %} + +### {{ definitions[category]['name'] }} + +{% for text, values in sections[""][category].items() %} +- {{ text }} {{ values|join(', ') }} +{% endfor %} + +{% endfor %} +{% else %} +No significant changes. + + +{% endif %} diff --git a/docs/_ext/saltdomain.py b/docs/_ext/saltdomain.py new file mode 100644 index 0000000..7a85489 --- /dev/null +++ b/docs/_ext/saltdomain.py @@ -0,0 +1,18 @@ +""" +Copied/distilled from Salt doc/_ext/saltdomain.py in order to be able +to use Salt's custom doc refs. +""" + + +def setup(app): + app.add_crossref_type( + directivename="conf_master", + rolename="conf_master", + indextemplate="pair: %s; conf/master", + ) + app.add_crossref_type( + directivename="conf_minion", + rolename="conf_minion", + indextemplate="pair: %s; conf/minion", + ) + return {"parallel_read_safe": True, "parallel_write_safe": True} diff --git a/docs/all.rst b/docs/all.rst deleted file mode 100644 index d7d50f0..0000000 --- a/docs/all.rst +++ /dev/null @@ -1,16 +0,0 @@ -.. _all the states/modules: - -Complete List of saltext-zabbix -============================= - - -.. toctree:: - :maxdepth: 2 - - ref/modules.rst - - -.. toctree:: - :maxdepth: 2 - - ref/states.rst diff --git a/docs/changelog.md b/docs/changelog.md new file mode 100644 index 0000000..2f5367b --- /dev/null +++ b/docs/changelog.md @@ -0,0 +1,12 @@ +# Changelog + +The changelog format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). + +This project uses [Semantic Versioning](https://semver.org/) - MAJOR.MINOR.PATCH + +```{towncrier-draft-entries} +``` + +```{include} ../CHANGELOG.md +:start-after: '# Changelog' +``` diff --git a/docs/conf.py b/docs/conf.py old mode 100644 new mode 100755 index 7891070..ba28057 --- a/docs/conf.py +++ b/docs/conf.py @@ -9,8 +9,10 @@ # documentation root, use os.path.abspath to make it absolute, like shown here. # import datetime +import email.policy import os import sys +from pathlib import Path try: from importlib_metadata import distribution @@ -25,25 +27,40 @@ # assume we're in the doc/ directory docs_basepath = os.path.abspath(os.path.dirname(".")) +PROJECT_ROOT_DIR = Path(docs_basepath).parent + addtl_paths = ( - os.path.join(os.pardir, "src"), # saltext.ttp itself (for autodoc) + os.path.join(os.pardir, "src"), # saltext.zabbix itself (for autodoc) "_ext", # custom Sphinx extensions ) for addtl_path in addtl_paths: sys.path.insert(0, os.path.abspath(os.path.join(docs_basepath, addtl_path))) -dist = distribution("saltext.saltext-zabbix") +dist = distribution("saltext.zabbix") # -- Project information ----------------------------------------------------- this_year = datetime.datetime.today().year -if this_year == 2021: - copyright_year = 2021 +if this_year == 2023: + copyright_year = "2023" else: - copyright_year = f"2021 - {this_year}" + copyright_year = f"2023 - {this_year}" project = dist.metadata["Summary"] -author = dist.metadata["Author"] +author = dist.metadata.get("Author") + +if author is None: + # Core metadata is serialized differently with pyproject.toml: + # https://packaging.python.org/en/latest/specifications/pyproject-toml/#authors-maintainers + author_email = dist.metadata["Author-email"] + em = email.message_from_string( + f"To: {author_email}", + policy=email.policy.default, + ) + if em["To"].addresses and em["To"].addresses[0]: + author = em["To"].addresses[0].display_name + author = author or "" + copyright = f"{copyright_year}, {author}" # The full version, including alpha/beta/rc tags @@ -62,11 +79,12 @@ # -- General configuration --------------------------------------------------- +linkcheck_ignore = [r"http://localhost:\d+"] + # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - "furo", "sphinx.ext.autodoc", "sphinx.ext.autosummary", "sphinx.ext.napoleon", @@ -76,6 +94,16 @@ "sphinx.ext.coverage", "sphinx_copybutton", "sphinxcontrib.spelling", + "saltdomain", + "sphinxcontrib.towncrier.ext", + "myst_parser", + "sphinx_inline_tabs", +] + +myst_enable_extensions = [ + "colon_fence", + "deflist", + "tasklist", ] # Add any paths that contain templates here, relative to this directory. @@ -96,7 +124,7 @@ "sitevars.rst", ] -autosummary_generate = True +autosummary_generate = False # -- Options for HTML output ------------------------------------------------- @@ -137,7 +165,7 @@ # ----- Intersphinx Config ----------------------------------------------------------------------------------------> intersphinx_mapping = { "python": ("https://docs.python.org/3", None), - "pytest": ("https://pytest.readthedocs.io/en/stable", None), + "pytest": ("https://docs.pytest.org/en/stable", None), "salt": ("https://docs.saltproject.io/en/latest", None), } # <---- Intersphinx Config ----------------------------------------------------------------------------------------- @@ -147,6 +175,11 @@ autodoc_mock_imports = ["salt"] # <---- Autodoc Config ----------------------------------------------------------------------------------------------- +# Towncrier draft config +towncrier_draft_autoversion_mode = "sphinx-release" +towncrier_draft_include_empty = True +towncrier_draft_working_directory = str(PROJECT_ROOT_DIR) + def setup(app): app.add_crossref_type( diff --git a/docs/index.rst b/docs/index.rst index 5d2e5c5..df83cb9 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,11 +1,31 @@ -Welcome to saltext-zabbix Documentation! -====================================== +``saltext-zabbix``: Integrate Salt with Zabbix +============================================== + +Salt Extension for interacting with Zabbix + +.. toctree:: + :maxdepth: 2 + :caption: Guides + :hidden: + + topics/installation .. toctree:: :maxdepth: 2 - :caption: Contents: + :caption: Provided Modules + :hidden: + + ref/modules/index + ref/returners/index + ref/states/index + +.. toctree:: + :maxdepth: 2 + :caption: Reference + :hidden: + + changelog - all.rst Indices and tables ================== diff --git a/docs/ref/modules/all/salt.modules.zabbix.rst b/docs/ref/modules/all/salt.modules.zabbix.rst deleted file mode 100644 index 470000d..0000000 --- a/docs/ref/modules/all/salt.modules.zabbix.rst +++ /dev/null @@ -1,5 +0,0 @@ -salt.modules.zabbix -=================== - -.. automodule:: salt.modules.zabbix - :members: diff --git a/docs/ref/modules/index.rst b/docs/ref/modules/index.rst new file mode 100644 index 0000000..51aa0c1 --- /dev/null +++ b/docs/ref/modules/index.rst @@ -0,0 +1,12 @@ +.. all-saltext.zabbix.modules: + +_________________ +Execution Modules +_________________ + +.. currentmodule:: saltext.zabbix.modules + +.. autosummary:: + :toctree: + + zabbix diff --git a/docs/ref/modules/saltext.zabbix.modules.zabbix.rst b/docs/ref/modules/saltext.zabbix.modules.zabbix.rst new file mode 100644 index 0000000..f221720 --- /dev/null +++ b/docs/ref/modules/saltext.zabbix.modules.zabbix.rst @@ -0,0 +1,5 @@ +``zabbix`` +========== + +.. automodule:: saltext.zabbix.modules.zabbix + :members: diff --git a/docs/ref/returners/all/salt.returners.zabbix_return.rst b/docs/ref/returners/all/salt.returners.zabbix_return.rst deleted file mode 100644 index c4026fe..0000000 --- a/docs/ref/returners/all/salt.returners.zabbix_return.rst +++ /dev/null @@ -1,6 +0,0 @@ -salt.returners.zabbix_return -============================ - -.. automodule:: salt.returners.zabbix_return - :members: - :undoc-members: diff --git a/docs/ref/returners/index.rst b/docs/ref/returners/index.rst new file mode 100644 index 0000000..c84c3f6 --- /dev/null +++ b/docs/ref/returners/index.rst @@ -0,0 +1,12 @@ +.. all-saltext.zabbix.returners: + +________________ +Returner Modules +________________ + +.. currentmodule:: saltext.zabbix.returners + +.. autosummary:: + :toctree: + + zabbix_return diff --git a/docs/ref/returners/saltext.zabbix.returners.zabbix_return.rst b/docs/ref/returners/saltext.zabbix.returners.zabbix_return.rst new file mode 100644 index 0000000..777b9cd --- /dev/null +++ b/docs/ref/returners/saltext.zabbix.returners.zabbix_return.rst @@ -0,0 +1,5 @@ +``zabbix`` +========== + +.. automodule:: saltext.zabbix.returners.zabbix_return + :members: diff --git a/docs/ref/states/all/salt.states.zabbix_action.rst b/docs/ref/states/all/salt.states.zabbix_action.rst deleted file mode 100644 index 9a838fc..0000000 --- a/docs/ref/states/all/salt.states.zabbix_action.rst +++ /dev/null @@ -1,5 +0,0 @@ -salt.states.zabbix_action -========================= - -.. automodule:: salt.states.zabbix_action - :members: diff --git a/docs/ref/states/all/salt.states.zabbix_host.rst b/docs/ref/states/all/salt.states.zabbix_host.rst deleted file mode 100644 index a968540..0000000 --- a/docs/ref/states/all/salt.states.zabbix_host.rst +++ /dev/null @@ -1,5 +0,0 @@ -salt.states.zabbix_host -======================= - -.. automodule:: salt.states.zabbix_host - :members: diff --git a/docs/ref/states/all/salt.states.zabbix_hostgroup.rst b/docs/ref/states/all/salt.states.zabbix_hostgroup.rst deleted file mode 100644 index 7370dce..0000000 --- a/docs/ref/states/all/salt.states.zabbix_hostgroup.rst +++ /dev/null @@ -1,5 +0,0 @@ -salt.states.zabbix_hostgroup -============================ - -.. automodule:: salt.states.zabbix_hostgroup - :members: diff --git a/docs/ref/states/all/salt.states.zabbix_mediatype.rst b/docs/ref/states/all/salt.states.zabbix_mediatype.rst deleted file mode 100644 index db04331..0000000 --- a/docs/ref/states/all/salt.states.zabbix_mediatype.rst +++ /dev/null @@ -1,6 +0,0 @@ -salt.states.zabbix_mediatype -============================ - -.. automodule:: salt.states.zabbix_mediatype - :members: - :undoc-members: diff --git a/docs/ref/states/all/salt.states.zabbix_template.rst b/docs/ref/states/all/salt.states.zabbix_template.rst deleted file mode 100644 index 00aed96..0000000 --- a/docs/ref/states/all/salt.states.zabbix_template.rst +++ /dev/null @@ -1,5 +0,0 @@ -salt.states.zabbix_template -=========================== - -.. automodule:: salt.states.zabbix_template - :members: diff --git a/docs/ref/states/all/salt.states.zabbix_user.rst b/docs/ref/states/all/salt.states.zabbix_user.rst deleted file mode 100644 index 6b3b501..0000000 --- a/docs/ref/states/all/salt.states.zabbix_user.rst +++ /dev/null @@ -1,5 +0,0 @@ -salt.states.zabbix_user -======================= - -.. automodule:: salt.states.zabbix_user - :members: diff --git a/docs/ref/states/all/salt.states.zabbix_usergroup.rst b/docs/ref/states/all/salt.states.zabbix_usergroup.rst deleted file mode 100644 index 78828d0..0000000 --- a/docs/ref/states/all/salt.states.zabbix_usergroup.rst +++ /dev/null @@ -1,5 +0,0 @@ -salt.states.zabbix_usergroup -============================ - -.. automodule:: salt.states.zabbix_usergroup - :members: diff --git a/docs/ref/states/all/salt.states.zabbix_usermacro.rst b/docs/ref/states/all/salt.states.zabbix_usermacro.rst deleted file mode 100644 index af472a4..0000000 --- a/docs/ref/states/all/salt.states.zabbix_usermacro.rst +++ /dev/null @@ -1,5 +0,0 @@ -salt.states.zabbix_usermacro -============================ - -.. automodule:: salt.states.zabbix_usermacro - :members: diff --git a/docs/ref/states/all/salt.states.zabbix_valuemap.rst b/docs/ref/states/all/salt.states.zabbix_valuemap.rst deleted file mode 100644 index c13a230..0000000 --- a/docs/ref/states/all/salt.states.zabbix_valuemap.rst +++ /dev/null @@ -1,5 +0,0 @@ -salt.states.zabbix_valuemap -=========================== - -.. automodule:: salt.states.zabbix_valuemap - :members: diff --git a/docs/ref/states/index.rst b/docs/ref/states/index.rst new file mode 100644 index 0000000..1272b89 --- /dev/null +++ b/docs/ref/states/index.rst @@ -0,0 +1,20 @@ +.. all-saltext.zabbix.states: + +_____________ +State Modules +_____________ + +.. currentmodule:: saltext.zabbix.states + +.. autosummary:: + :toctree: + + zabbix_action + zabbix_host + zabbix_hostgroup + zabbix_mediatype + zabbix_template + zabbix_user + zabbix_usergroup + zabbix_usermacro + zabbix_valuemap diff --git a/docs/ref/states/saltext.zabbix.states.zabbix_action.rst b/docs/ref/states/saltext.zabbix.states.zabbix_action.rst new file mode 100644 index 0000000..394d2f4 --- /dev/null +++ b/docs/ref/states/saltext.zabbix.states.zabbix_action.rst @@ -0,0 +1,5 @@ +``zabbix_action`` +================= + +.. automodule:: saltext.zabbix.states.zabbix_action + :members: diff --git a/docs/ref/states/saltext.zabbix.states.zabbix_host.rst b/docs/ref/states/saltext.zabbix.states.zabbix_host.rst new file mode 100644 index 0000000..3710cdc --- /dev/null +++ b/docs/ref/states/saltext.zabbix.states.zabbix_host.rst @@ -0,0 +1,5 @@ +``zabbix_host`` +=============== + +.. automodule:: saltext.zabbix.states.zabbix_host + :members: diff --git a/docs/ref/states/saltext.zabbix.states.zabbix_hostgroup.rst b/docs/ref/states/saltext.zabbix.states.zabbix_hostgroup.rst new file mode 100644 index 0000000..c70f5e6 --- /dev/null +++ b/docs/ref/states/saltext.zabbix.states.zabbix_hostgroup.rst @@ -0,0 +1,5 @@ +``zabbix_hostgroup`` +==================== + +.. automodule:: saltext.zabbix.states.zabbix_hostgroup + :members: diff --git a/docs/ref/states/saltext.zabbix.states.zabbix_mediatype.rst b/docs/ref/states/saltext.zabbix.states.zabbix_mediatype.rst new file mode 100644 index 0000000..b1daff3 --- /dev/null +++ b/docs/ref/states/saltext.zabbix.states.zabbix_mediatype.rst @@ -0,0 +1,5 @@ +``zabbix_mediatype`` +==================== + +.. automodule:: saltext.zabbix.states.zabbix_mediatype + :members: diff --git a/docs/ref/states/saltext.zabbix.states.zabbix_template.rst b/docs/ref/states/saltext.zabbix.states.zabbix_template.rst new file mode 100644 index 0000000..01dfe5a --- /dev/null +++ b/docs/ref/states/saltext.zabbix.states.zabbix_template.rst @@ -0,0 +1,5 @@ +``zabbix_template`` +=================== + +.. automodule:: saltext.zabbix.states.zabbix_template + :members: diff --git a/docs/ref/states/saltext.zabbix.states.zabbix_user.rst b/docs/ref/states/saltext.zabbix.states.zabbix_user.rst new file mode 100644 index 0000000..6f7fcb8 --- /dev/null +++ b/docs/ref/states/saltext.zabbix.states.zabbix_user.rst @@ -0,0 +1,5 @@ +``zabbix_user`` +=============== + +.. automodule:: saltext.zabbix.states.zabbix_user + :members: diff --git a/docs/ref/states/saltext.zabbix.states.zabbix_usergroup.rst b/docs/ref/states/saltext.zabbix.states.zabbix_usergroup.rst new file mode 100644 index 0000000..125ce4f --- /dev/null +++ b/docs/ref/states/saltext.zabbix.states.zabbix_usergroup.rst @@ -0,0 +1,5 @@ +``zabbix_usergroup`` +==================== + +.. automodule:: saltext.zabbix.states.zabbix_usergroup + :members: diff --git a/docs/ref/states/saltext.zabbix.states.zabbix_usermacro.rst b/docs/ref/states/saltext.zabbix.states.zabbix_usermacro.rst new file mode 100644 index 0000000..57ffd14 --- /dev/null +++ b/docs/ref/states/saltext.zabbix.states.zabbix_usermacro.rst @@ -0,0 +1,5 @@ +``zabbix_usermacro`` +==================== + +.. automodule:: saltext.zabbix.states.zabbix_usermacro + :members: diff --git a/docs/ref/states/saltext.zabbix.states.zabbix_valuemap.rst b/docs/ref/states/saltext.zabbix.states.zabbix_valuemap.rst new file mode 100644 index 0000000..17861bc --- /dev/null +++ b/docs/ref/states/saltext.zabbix.states.zabbix_valuemap.rst @@ -0,0 +1,5 @@ +``zabbix_valuemap`` +=================== + +.. automodule:: saltext.zabbix.states.zabbix_valuemap + :members: diff --git a/docs/topics/installation.md b/docs/topics/installation.md new file mode 100644 index 0000000..f3179ec --- /dev/null +++ b/docs/topics/installation.md @@ -0,0 +1,28 @@ +# Installation + +Generally, extensions need to be installed into the same Python environment Salt uses. + +:::{tab} State +```yaml +Install Salt Zabbix extension: + pip.installed: + - name: saltext-zabbix +``` +::: + +:::{tab} Onedir installation +```bash +salt-pip install saltext-zabbix +``` +::: + +:::{tab} Regular installation +```bash +pip install saltext-zabbix +``` +::: + +:::{hint} +Saltexts are not distributed automatically via the fileserver like custom modules, they need to be installed +on each node you want them to be available on. +::: diff --git a/noxfile.py b/noxfile.py old mode 100644 new mode 100755 index 3bf4f21..22a817c --- a/noxfile.py +++ b/noxfile.py @@ -19,17 +19,17 @@ nox.options.error_on_missing_interpreters = False # Python versions to test against -PYTHON_VERSIONS = ("3", "3.5", "3.6", "3.7", "3.8", "3.9") +PYTHON_VERSIONS = ("3", "3.8", "3.9", "3.10", "3.11", "3.12") # Be verbose when running under a CI context CI_RUN = ( os.environ.get("JENKINS_URL") or os.environ.get("CI") or os.environ.get("DRONE") is not None ) PIP_INSTALL_SILENT = CI_RUN is False -SKIP_REQUIREMENTS_INSTALL = "SKIP_REQUIREMENTS_INSTALL" in os.environ +SKIP_REQUIREMENTS_INSTALL = os.environ.get("SKIP_REQUIREMENTS_INSTALL", "0") == "1" EXTRA_REQUIREMENTS_INSTALL = os.environ.get("EXTRA_REQUIREMENTS_INSTALL") -COVERAGE_VERSION_REQUIREMENT = "coverage==5.2" -SALT_REQUIREMENT = os.environ.get("SALT_REQUIREMENT") or "salt>=3003rc1" +COVERAGE_REQUIREMENT = os.environ.get("COVERAGE_REQUIREMENT") or "coverage==7.5.1" +SALT_REQUIREMENT = os.environ.get("SALT_REQUIREMENT") or "salt>=3006" if SALT_REQUIREMENT == "salt==master": SALT_REQUIREMENT = "git+https://github.com/saltstack/salt.git@master" @@ -44,9 +44,8 @@ ARTIFACTS_DIR = REPO_ROOT / "artifacts" # Make sure the artifacts directory exists ARTIFACTS_DIR.mkdir(parents=True, exist_ok=True) -RUNTESTS_LOGFILE = ARTIFACTS_DIR / "runtests-{}.log".format( - datetime.datetime.now().strftime("%Y%m%d%H%M%S.%f") -) +CUR_TIME = datetime.datetime.now().strftime("%Y%m%d%H%M%S.%f") +RUNTESTS_LOGFILE = ARTIFACTS_DIR / f"runtests-{CUR_TIME}.log" COVERAGE_REPORT_DB = REPO_ROOT / ".coverage" COVERAGE_REPORT_PROJECT = ARTIFACTS_DIR.relative_to(REPO_ROOT) / "coverage-project.xml" COVERAGE_REPORT_TESTS = ARTIFACTS_DIR.relative_to(REPO_ROOT) / "coverage-tests.xml" @@ -59,7 +58,8 @@ def _get_session_python_version_info(session): except AttributeError: session_py_version = session.run_always( "python", - "-c" 'import sys; sys.stdout.write("{}.{}.{}".format(*sys.version_info))', + "-c", + 'import sys; sys.stdout.write("{}.{}.{}".format(*sys.version_info))', silent=True, log=False, ) @@ -70,14 +70,14 @@ def _get_session_python_version_info(session): def _get_pydir(session): version_info = _get_session_python_version_info(session) - if version_info < (3, 5): - session.error("Only Python >= 3.5 is supported") - return "py{}.{}".format(*version_info) + if version_info < (3, 8): + session.error("Only Python >= 3.8 is supported") + return f"py{version_info[0]}.{version_info[1]}" def _install_requirements( session, - *passed_requirements, + *passed_requirements, # pylint: disable=unused-argument install_coverage_requirements=True, install_test_requirements=True, install_source=False, @@ -89,9 +89,7 @@ def _install_requirements( # Always have the wheel package installed session.install("--progress-bar=off", "wheel", silent=PIP_INSTALL_SILENT) if install_coverage_requirements: - session.install( - "--progress-bar=off", COVERAGE_VERSION_REQUIREMENT, silent=PIP_INSTALL_SILENT - ) + session.install("--progress-bar=off", COVERAGE_REQUIREMENT, silent=PIP_INSTALL_SILENT) if install_salt: session.install("--progress-bar=off", SALT_REQUIREMENT, silent=PIP_INSTALL_SILENT) @@ -108,7 +106,7 @@ def _install_requirements( ) install_command = ["--progress-bar=off"] install_command += [req.strip() for req in EXTRA_REQUIREMENTS_INSTALL.split()] - session.install(*passed_requirements, silent=PIP_INSTALL_SILENT) + session.install(*install_command, silent=PIP_INSTALL_SILENT) if install_source: pkg = "." @@ -195,7 +193,7 @@ def tests(session): "-o", str(COVERAGE_REPORT_PROJECT), "--omit=tests/*", - "--include=src/saltext/saltext_zabbix/*", + "--include=src/saltext/zabbix/*", ) # Generate report for tests code coverage session.run( @@ -203,18 +201,16 @@ def tests(session): "xml", "-o", str(COVERAGE_REPORT_TESTS), - "--omit=src/saltext/saltext_zabbix/*", + "--omit=src/saltext/zabbix/*", "--include=tests/*", ) try: - session.run( - "coverage", "report", "--show-missing", "--include=src/saltext/saltext_zabbix/*" - ) + session.run("coverage", "report", "--show-missing", "--include=src/saltext/zabbix/*") # If you also want to display the code coverage report on the CLI # for the tests, comment the call above and uncomment the line below # session.run( # "coverage", "report", "--show-missing", - # "--include=src/saltext/saltext_zabbix/*,tests/*" + # "--include=src/saltext/zabbix/*,tests/*" # ) finally: # Move the coverage DB to artifacts/coverage in order for it to be archived by CI @@ -292,7 +288,7 @@ def _lint(session, rcfile, flags, paths, tee_output=True): sys.stdout.flush() if pylint_report_path: # Write report - with open(pylint_report_path, "w") as wfh: + with open(pylint_report_path, "w", encoding="utf-8") as wfh: wfh.write(contents) session.log("Report file written to %r", pylint_report_path) stdout.close() @@ -307,9 +303,7 @@ def _lint_pre_commit(session, rcfile, flags, paths): if "pre-commit" not in os.environ["VIRTUAL_ENV"]: session.error( "This should be running from within a pre-commit virtualenv and " - "'VIRTUAL_ENV'({}) does not appear to be a pre-commit virtualenv.".format( - os.environ["VIRTUAL_ENV"] - ) + f"'VIRTUAL_ENV'({os.environ['VIRTUAL_ENV']}) does not appear to be a pre-commit virtualenv." ) # Let's patch nox to make it run inside the pre-commit virtualenv @@ -405,7 +399,7 @@ def docs(session): session.run("make", "coverage", "SPHINXOPTS=-W", external=True) docs_coverage_file = os.path.join("_build", "html", "python.txt") if os.path.exists(docs_coverage_file): - with open(docs_coverage_file) as rfh: + with open(docs_coverage_file) as rfh: # pylint: disable=unspecified-encoding contents = rfh.readlines()[2:] if contents: session.error("\n" + "".join(contents)) @@ -489,20 +483,15 @@ def docs_crosslink_info(session): log=False, ) ) + intersphinx_mapping_list = ", ".join(list(intersphinx_mapping)) try: mapping_entry = intersphinx_mapping[session.posargs[0]] except IndexError: session.error( - "You need to pass at least one argument whose value must be one of: {}".format( - ", ".join(list(intersphinx_mapping)) - ) + f"You need to pass at least one argument whose value must be one of: {intersphinx_mapping_list}" ) except KeyError: - session.error( - "Only acceptable values for first argument are: {}".format( - ", ".join(list(intersphinx_mapping)) - ) - ) + session.error(f"Only acceptable values for first argument are: {intersphinx_mapping_list}") session.run( "python", "-m", "sphinx.ext.intersphinx", mapping_entry[0].rstrip("/") + "/objects.inv" ) @@ -521,7 +510,10 @@ def gen_api_docs(session): install_source=True, install_extras=["docs"], ) - shutil.rmtree("docs/ref") + try: + shutil.rmtree("docs/ref") + except FileNotFoundError: + pass session.run( "sphinx-apidoc", "--implicit-namespaces", @@ -529,5 +521,5 @@ def gen_api_docs(session): "-o", "docs/ref/", "src/saltext", - "src/saltext/saltext_zabbix/config/schemas", + "src/saltext/zabbix/config/schemas", ) diff --git a/pyproject.toml b/pyproject.toml index 6bc25aa..22df7e4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,154 @@ [build-system] -requires = ["setuptools>=50.3.2", "wheel", "setuptools-declarative-requirements", "setuptools_scm[toml]>=3.4"] +requires = [ + "wheel", + "setuptools>=50.3.2", + "setuptools_scm[toml]>=3.4", +] build-backend = "setuptools.build_meta" [tool.setuptools_scm] -write_to = "src/saltext/saltext_zabbix/version.py" +write_to = "src/saltext/zabbix/version.py" write_to_template = "__version__ = \"{version}\"" +[project] +name = "saltext.zabbix" +description = "Salt Extension for interacting with Zabbix" +authors = [ + {name = "Salt Core Team", email = "saltproject@vmware.com"}, +] +keywords = [ + "salt-extension", +] +license = {text = "Apache Software License"} +classifiers = [ + "Programming Language :: Python", + "Programming Language :: Cython", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", +] +requires-python = ">= 3.8" +dynamic = ["version"] +dependencies = [ + "salt>=3006", +] + +[project.readme] +file = "README.md" +content-type = "text/markdown" + +[project.urls] +Homepage = "https://github.com/salt-extensions/saltext-zabbix" +Documentation = "https://salt-extensions.github.io/saltext-zabbix/" +Source = "https://github.com/salt-extensions/saltext-zabbix" +Tracker = "https://github.com/salt-extensions/saltext-zabbix/issues" + +[project.optional-dependencies] +changelog = ["towncrier==22.12.0"] +dev = [ + "nox", + "pre-commit>=2.4.0", + "pylint", + "saltpylint", +] +docs = [ + "sphinx", + "sphinx-prompt", + "sphinxcontrib-spelling", + "sphinx-copybutton", + "towncrier==22.12.0", + "sphinxcontrib-towncrier", + "myst_parser", + "furo", + "sphinx-inline-tabs", +] +docsauto = ["sphinx-autobuild"] +lint = [ + "pylint", + "saltpylint", +] +tests = [ + "pytest>=7.2.0", + "pytest-salt-factories>=1.0.0; sys_platform == 'win32'", + "pytest-salt-factories[docker]>=1.0.0; sys_platform != 'win32'", +] + +[project.entry-points."salt.loader"] +"saltext.zabbix" = "saltext.zabbix" + +[tool.setuptools] +zip-safe = false +include-package-data = true +platforms = ["any"] + +[tool.setuptools.packages.find] +where = ["src"] +exclude = ["tests"] + +[tool.distutils.bdist_wheel] +# Use this option if your package is pure-python +universal = 1 + +[tool.distutils.sdist] +owner = "root" +group = "root" + +[tool.build_sphinx] +source_dir = "docs" +build_dir = "build/sphinx" + [tool.black] line-length = 100 + +[tool.isort] +force_single_line = true +skip = ["src/saltext/zabbix/__init__.py"] +profile = "black" +line_length = 100 + +[tool.towncrier] +package = "saltext.zabbix" +filename = "CHANGELOG.md" +template = "changelog/.template.jinja" +directory = "changelog/" +start_string = "# Changelog\n" +underlines = ["", "", ""] +title_format = "## {version} ({project_date})" +issue_format = "[#{issue}](https://github.com/salt-extensions/saltext-zabbix/issues/{issue})" + +[[tool.towncrier.type]] +directory = "removed" +name = "Removed" +showcontent = true + +[[tool.towncrier.type]] +directory = "deprecated" +name = "Deprecated" +showcontent = true + +[[tool.towncrier.type]] +directory = "changed" +name = "Changed" +showcontent = true + +[[tool.towncrier.type]] +directory = "fixed" +name = "Fixed" +showcontent = true + +[[tool.towncrier.type]] +directory = "added" +name = "Added" +showcontent = true + +[[tool.towncrier.type]] +directory = "security" +name = "Security" +showcontent = true diff --git a/requirements/changelog.txt b/requirements/changelog.txt deleted file mode 100644 index fe1c872..0000000 --- a/requirements/changelog.txt +++ /dev/null @@ -1 +0,0 @@ -towncrier==21.9.0rc1 diff --git a/requirements/dev.txt b/requirements/dev.txt deleted file mode 100644 index e26ef85..0000000 --- a/requirements/dev.txt +++ /dev/null @@ -1,4 +0,0 @@ --r base.txt -nox==2021.6.12 -pre-commit==2.13.0 -pylint diff --git a/requirements/docs-auto.txt b/requirements/docs-auto.txt deleted file mode 100644 index 231419d..0000000 --- a/requirements/docs-auto.txt +++ /dev/null @@ -1 +0,0 @@ -sphinx-autobuild diff --git a/requirements/docs.txt b/requirements/docs.txt deleted file mode 100644 index a9debea..0000000 --- a/requirements/docs.txt +++ /dev/null @@ -1,9 +0,0 @@ --r base.txt --r changelog.txt -sphinx -furo -sphinx-copybutton -sphinx-prompt -sphinxcontrib-spelling -importlib_metadata; python_version < "3.8" -pyyaml diff --git a/requirements/tests.txt b/requirements/tests.txt deleted file mode 100644 index be9128b..0000000 --- a/requirements/tests.txt +++ /dev/null @@ -1,15 +0,0 @@ --r base.txt -mock >= 3.0.0 -# PyTest -pytest >= 7.0.1; python_version <= "3.6" -pytest >= 7.2.0; python_version > "3.6" -pytest-salt-factories >= 1.0.0rc21; sys_platform == 'win32' -pytest-salt-factories[docker] >= 1.0.0rc21; sys_platform != 'win32' -pytest-tempdir >= 2019.10.12 -pytest-helpers-namespace >= 2019.1.8 -pytest-subtests -pytest-timeout -pytest-httpserver -pytest-custom-exit-code >= 0.3 -flaky -markupsafe==2.0.1 diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 7a02560..0000000 --- a/setup.cfg +++ /dev/null @@ -1,77 +0,0 @@ -[metadata] -name = saltext.saltext-zabbix -description = Salt Extension for interacting with Zabbix -long_description = file: README.md -long_description_content_type = text/markdown -author = Salt Core Team -author_email = saltproject@vmware.com -keywords = salt-extension -url = http://example.com -project_urls = - Source=http://example.com - Tracker=http://example.com/issues -license = Apache Software License -classifiers = - Programming Language :: Python - Programming Language :: Cython - Programming Language :: Python :: 3 - Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3.7 - Programming Language :: Python :: 3.8 - Programming Language :: Python :: 3.9 - Development Status :: 4 - Beta - Intended Audience :: Developers - License :: OSI Approved :: Apache Software License -platforms = any - -[options] -zip_safe = False -include_package_data = True -package_dir = - =src -packages = find_namespace: -python_requires = >= 3.5 -setup_requires = - wheel - setuptools>=50.3.2 - setuptools_scm[toml]>=3.4 - setuptools-declarative-requirements -install_requires = - salt>=3003 - # Add other module install requirements above this line - -[options.packages.find] -where = src -exclude = - tests - -# When targetting Salt < 3003, you can remove the other 'options.entry_points' section and use this one -#[options.entry_points] -#salt.loader= -# - -[options.entry_points] -salt.loader= - saltext.salt-zabbix = saltext.saltext_zabbix - -[requirements-files] -install_requires = requirements/base.txt -tests_require = requirements/tests.txt -extras_require = - dev = requirements/dev.txt - tests = requirements/tests.txt - docs = requirements/docs.txt - docsauto = requirements/docs-auto.txt - changelog = requirements/changelog.txt - -[bdist_wheel] -# Use this option if your package is pure-python -universal = 1 - -[build_sphinx] -source_dir = docs -build_dir = build/sphinx - -[sdist] -owner = root -group = root diff --git a/src/saltext/saltext_zabbix/loader.py b/src/saltext/saltext_zabbix/loader.py deleted file mode 100644 index 5d2e0b6..0000000 --- a/src/saltext/saltext_zabbix/loader.py +++ /dev/null @@ -1,5 +0,0 @@ -""" -Define the required entry-points functions in order for Salt to know -what and from where it should load this extension's loaders -""" -from . import PACKAGE_ROOT # pylint: disable=unused-import diff --git a/src/saltext/saltext_zabbix/__init__.py b/src/saltext/zabbix/__init__.py similarity index 100% rename from src/saltext/saltext_zabbix/__init__.py rename to src/saltext/zabbix/__init__.py diff --git a/docs/ref/.gitkeep b/src/saltext/zabbix/modules/__init__.py similarity index 100% rename from docs/ref/.gitkeep rename to src/saltext/zabbix/modules/__init__.py diff --git a/src/saltext/saltext_zabbix/modules/zabbix.py b/src/saltext/zabbix/modules/zabbix.py similarity index 98% rename from src/saltext/saltext_zabbix/modules/zabbix.py rename to src/saltext/zabbix/modules/zabbix.py index 699fd82..c365a8d 100644 --- a/src/saltext/saltext_zabbix/modules/zabbix.py +++ b/src/saltext/zabbix/modules/zabbix.py @@ -22,6 +22,7 @@ :codeauthor: Jiri Kotlin """ + import logging import os import socket @@ -176,19 +177,15 @@ def _query(method, params, url, auth=None): ) log.info("_QUERY result: %s", str(result)) if "error" in result: - raise SaltException( - "Zabbix API: Status: {} ({})".format(result["status"], result["error"]) - ) + raise SaltException(f"Zabbix API: Status: {result['status']} ({result['error']})") ret = result.get("dict", {}) if "error" in ret: - raise SaltException( - "Zabbix API: {} ({})".format(ret["error"]["message"], ret["error"]["data"]) - ) + raise SaltException(f"Zabbix API: {ret['error']['message']} ({ret['error']['data']})") return ret except ValueError as err: - raise SaltException(f"URL or HTTP headers are probably not correct! ({err})") + raise SaltException(f"URL or HTTP headers are probably not correct! ({err})") from err except OSError as err: - raise SaltException(f"Check hostname in URL! ({err})") + raise SaltException(f"Check hostname in URL! ({err})") from err def _login(**kwargs): @@ -253,7 +250,7 @@ def _connarg(name, key=None): else: raise KeyError except KeyError as err: - raise SaltException(f"URL is probably not correct! ({err})") + raise SaltException(f"URL is probably not correct! ({err})") from err def _params_extend(params, _ignore_name=False, **kwargs): @@ -274,9 +271,9 @@ def _params_extend(params, _ignore_name=False, **kwargs): """ # extend params value by optional zabbix API parameters - for key in kwargs: + for key, val in kwargs.items(): if not key.startswith("_"): - params.setdefault(key, kwargs[key]) + params.setdefault(key, val) # ignore name parameter passed from Salt state module, use firstname or visible_name instead if _ignore_name: @@ -357,11 +354,10 @@ def substitute_params(input_object, extend_params=None, filter_key="name", **kwa try: query_params.update({"filter": {filter_key: input_object["query_name"]}}) return get_object_id_by_params(input_object["query_object"], query_params, **kwargs) - except KeyError: + except KeyError as err: raise SaltException( - "Qyerying object ID requested " - "but object name not provided: {}".format(input_object) - ) + f"Querying object ID requested but object name not provided: {input_object}" + ) from err else: return { key: substitute_params(val, extend_params, filter_key, **kwargs) @@ -394,10 +390,8 @@ def compare_params(defined, existing, return_old_value=False): # Comparison of data types if not isinstance(defined, type(existing)): raise SaltException( - "Zabbix object comparison failed (data type mismatch). Expecting {}, got" - ' {}. Existing value: "{}", defined value: "{}").'.format( - type(existing), type(defined), existing, defined - ) + f"Zabbix object comparison failed (data type mismatch). Expecting {type(existing)}," + f' got {type(defined)}. Existing value: "{existing}", defined value: "{defined}").' ) # Comparison of values @@ -450,13 +444,11 @@ def compare_params(defined, existing, return_old_value=False): return {"new": defined, "old": existing} if return_old_value else defined - except TypeError: + except TypeError as err: raise SaltException( - "Zabbix object comparison failed (data type mismatch). Expecting {}," - ' got {}. Existing value: "{}", defined value: "{}").'.format( - type(existing), type(defined), existing, defined - ) - ) + f"Zabbix object comparison failed (data type mismatch). Expecting {type(existing)}," + f' got {type(defined)}. Existing value: "{existing}", defined value: "{defined}").' + ) from err def get_object_id_by_params(obj, params=None, **connection_args): @@ -487,9 +479,7 @@ def get_object_id_by_params(obj, params=None, **connection_args): else: raise SaltException( "Zabbix API: Object does not exist or bad Zabbix user permissions or other" - " unexpected result. Called method {} with params {}. Result: {}".format( - obj + ".get", params, res - ) + f" unexpected result. Called method {obj}.get with params {params}. Result: {res}" ) @@ -991,7 +981,7 @@ def usergroup_create(name, **connection_args): This function accepts all standard user group properties: keyword argument names differ depending on your zabbix version, see here__. - .. __: https://www.zabbix.com/documentation/2.0/manual/appendix/api/usergroup/definitions#user_group + .. __: https://www.zabbix.com/documentation/2.0/manual/appendix/api/usergroup/definitions#user-group :param name: name of the user group :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring) @@ -1182,7 +1172,7 @@ def usergroup_update(usrgrpid, **connection_args): This function accepts all standard user group properties: keyword argument names differ depending on your zabbix version, see here__. - .. __: https://www.zabbix.com/documentation/2.4/manual/api/reference/usergroup/object#user_group + .. __: https://www.zabbix.com/documentation/2.4/manual/api/reference/usergroup/object#user-group :param usrgrpid: ID of the user group to update. :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring) @@ -1510,7 +1500,7 @@ def host_update(hostid, **connection_args): def host_inventory_get(hostids, **connection_args): """ Retrieve host inventory according to the given parameters. - See: https://www.zabbix.com/documentation/2.4/manual/api/reference/host/object#host_inventory + See: https://www.zabbix.com/documentation/2.4/manual/api/reference/host/object#host-inventory .. versionadded:: 2019.2.0 @@ -1552,7 +1542,7 @@ def host_inventory_set(hostid, **connection_args): """ Update host inventory items NOTE: This function accepts all standard host: keyword argument names for inventory - see: https://www.zabbix.com/documentation/2.4/manual/api/reference/host/object#host_inventory + see: https://www.zabbix.com/documentation/2.4/manual/api/reference/host/object#host-inventory .. versionadded:: 2019.2.0 @@ -1650,7 +1640,7 @@ def hostgroup_create(name, **connection_args): This function accepts all standard host group properties: keyword argument names differ depending on your zabbix version, see here__. - .. __: https://www.zabbix.com/documentation/2.4/manual/api/reference/hostgroup/object#host_group + .. __: https://www.zabbix.com/documentation/2.4/manual/api/reference/hostgroup/object#host-group :param name: name of the host group :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring) @@ -1846,7 +1836,7 @@ def hostgroup_update(groupid, name=None, **connection_args): This function accepts all standard host group properties: keyword argument names differ depending on your zabbix version, see here__. - .. __: https://www.zabbix.com/documentation/2.4/manual/api/reference/hostgroup/object#host_group + .. __: https://www.zabbix.com/documentation/2.4/manual/api/reference/hostgroup/object#host-group :param groupid: ID of the host group to update :param name: name of the host group @@ -2079,7 +2069,7 @@ def hostinterface_update(interfaceid, **connection_args): This function accepts all standard hostinterface: keyword argument names differ depending on your zabbix version, see here__. - .. __: https://www.zabbix.com/documentation/2.4/manual/api/reference/hostinterface/object#host_interface + .. __: https://www.zabbix.com/documentation/2.4/manual/api/reference/hostinterface/object#host-interface :param interfaceid: ID of the hostinterface to update diff --git a/requirements/base.txt b/src/saltext/zabbix/returners/__init__.py similarity index 100% rename from requirements/base.txt rename to src/saltext/zabbix/returners/__init__.py diff --git a/src/saltext/saltext_zabbix/returners/zabbix_return.py b/src/saltext/zabbix/returners/zabbix_return.py similarity index 92% rename from src/saltext/saltext_zabbix/returners/zabbix_return.py rename to src/saltext/zabbix/returners/zabbix_return.py index 1488b31..9120d20 100644 --- a/src/saltext/saltext_zabbix/returners/zabbix_return.py +++ b/src/saltext/zabbix/returners/zabbix_return.py @@ -15,6 +15,7 @@ salt '*' test.ping --return zabbix """ + import os # Define the module's virtual name @@ -66,13 +67,13 @@ def returner(ret): errors = True zabbix_send( "salt.trap.high", - "SALT:\nname: {}\ncomment: {}".format(item["name"], item["comment"]), + f"SALT:\nname: {item['name']}\ncomment: {item['comment']}", ) elif "comment" in item and "name" in item and item["changes"]: changes = True zabbix_send( "salt.trap.warning", - "SALT:\nname: {}\ncomment: {}".format(item["name"], item["comment"]), + f"SALT:\nname: {item['name']}\ncomment: {item['comment']}", ) if not changes and not errors: diff --git a/src/saltext/zabbix/states/__init__.py b/src/saltext/zabbix/states/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/saltext/saltext_zabbix/states/zabbix_action.py b/src/saltext/zabbix/states/zabbix_action.py similarity index 95% rename from src/saltext/saltext_zabbix/states/zabbix_action.py rename to src/saltext/zabbix/states/zabbix_action.py index 8271713..e9adab0 100644 --- a/src/saltext/saltext_zabbix/states/zabbix_action.py +++ b/src/saltext/zabbix/states/zabbix_action.py @@ -5,6 +5,7 @@ :codeauthor: Jakub Sliva """ + import json import logging @@ -128,8 +129,8 @@ def present(name, params, **kwargs): ret["changes"] = { name: { "old": ( - 'Zabbix Action "{}" differs ' - "in following parameters: {}".format(name, diff_params) + f'Zabbix Action "{name}" differs ' + f"in following parameters: {diff_params}" ), "new": (f'Zabbix Action "{name}" would correspond to definition.'), } @@ -146,8 +147,8 @@ def present(name, params, **kwargs): ret["changes"] = { name: { "old": ( - 'Zabbix Action "{}" differed ' - "in following parameters: {}".format(name, diff_params) + f'Zabbix Action "{name}" differed ' + f"in following parameters: {diff_params}" ), "new": f'Zabbix Action "{name}" fixed.', } @@ -155,9 +156,9 @@ def present(name, params, **kwargs): else: ret["result"] = True - ret[ - "comment" - ] = f'Zabbix Action "{name}" already exists and corresponds to a definition.' + ret["comment"] = ( + f'Zabbix Action "{name}" already exists and corresponds to a definition.' + ) else: if dry_run: diff --git a/src/saltext/saltext_zabbix/states/zabbix_host.py b/src/saltext/zabbix/states/zabbix_host.py similarity index 98% rename from src/saltext/saltext_zabbix/states/zabbix_host.py rename to src/saltext/zabbix/states/zabbix_host.py index 63a78ba..ddfe756 100644 --- a/src/saltext/saltext_zabbix/states/zabbix_host.py +++ b/src/saltext/zabbix/states/zabbix_host.py @@ -5,6 +5,7 @@ """ + from collections.abc import Mapping from copy import deepcopy @@ -285,11 +286,11 @@ def _interface_format(interfaces_data): update_inventory = False host_updated_params = {} - for param in host_extra_properties: + for param, val in host_extra_properties.items(): if param in host: - if host[param] == host_extra_properties[param]: + if host[param] == val: continue - host_updated_params[param] = host_extra_properties[param] + host_updated_params[param] = val if host_updated_params: update_host = True @@ -480,8 +481,8 @@ def _update_interfaces(interface): error.append(updatedint["error"]) # And finally remove the ones that isn't in the host state - for interface_type in interfaceid_by_type: - for interfaceid in interfaceid_by_type[interface_type]: + for interface_type, ids in interfaceid_by_type.items(): + for interfaceid in ids: __salt__["zabbix.hostinterface_delete"]( interfaceids=interfaceid, **connection_args ) diff --git a/src/saltext/saltext_zabbix/states/zabbix_hostgroup.py b/src/saltext/zabbix/states/zabbix_hostgroup.py similarity index 100% rename from src/saltext/saltext_zabbix/states/zabbix_hostgroup.py rename to src/saltext/zabbix/states/zabbix_hostgroup.py diff --git a/src/saltext/saltext_zabbix/states/zabbix_mediatype.py b/src/saltext/zabbix/states/zabbix_mediatype.py similarity index 99% rename from src/saltext/saltext_zabbix/states/zabbix_mediatype.py rename to src/saltext/zabbix/states/zabbix_mediatype.py index c5b5151..44389fe 100644 --- a/src/saltext/saltext_zabbix/states/zabbix_mediatype.py +++ b/src/saltext/zabbix/states/zabbix_mediatype.py @@ -20,7 +20,7 @@ def present(name, mediatype, **kwargs): Creates new mediatype. NOTE: This function accepts all standard mediatype properties: keyword argument names differ depending on your zabbix version, see: - https://www.zabbix.com/documentation/3.0/manual/api/reference/host/object#host_inventory + https://www.zabbix.com/documentation/3.0/manual/api/reference/host/object#host-inventory :param name: name of the mediatype :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring) diff --git a/src/saltext/saltext_zabbix/states/zabbix_template.py b/src/saltext/zabbix/states/zabbix_template.py similarity index 97% rename from src/saltext/saltext_zabbix/states/zabbix_template.py rename to src/saltext/zabbix/states/zabbix_template.py index d627b63..e5e0e27 100644 --- a/src/saltext/saltext_zabbix/states/zabbix_template.py +++ b/src/saltext/zabbix/states/zabbix_template.py @@ -5,6 +5,7 @@ :codeauthor: Jakub Sliva """ + import json import logging @@ -291,8 +292,8 @@ def _diff_and_merge_host_list(defined, existing): try: defined_host_ids = {host["hostid"] for host in defined} existing_host_ids = {host["hostid"] for host in existing} - except KeyError: - raise SaltException("List of hosts in template not defined correctly.") + except KeyError as err: + raise SaltException("List of hosts in template not defined correctly.") from err diff = defined_host_ids - existing_host_ids return [{"hostid": str(hostid)} for hostid in diff | existing_host_ids] if diff else [] @@ -335,11 +336,9 @@ def _adjust_object_lists(obj): :param obj: Zabbix object parameters """ - for subcomp in TEMPLATE_COMPONENT_DEF: - if subcomp in obj and TEMPLATE_COMPONENT_DEF[subcomp]["adjust"]: - obj[subcomp] = [ - item[TEMPLATE_COMPONENT_DEF[subcomp]["qidname"]] for item in obj[subcomp] - ] + for subcomp, defs in TEMPLATE_COMPONENT_DEF.items(): + if subcomp in obj and defs["adjust"]: + obj[subcomp] = [item[defs["qidname"]] for item in obj[subcomp]] def _manage_component(component, parent_id, defined, existing, template_id=None, **kwargs): @@ -850,10 +849,7 @@ def present(name, params, static_host_list=True, **kwargs): ret["changes"] = { name: { "old": f'Zabbix Template "{name}" does not exist.', - "new": ( - 'Zabbix Template "{}" would be created ' - "according definition.".format(name) - ), + "new": f'Zabbix Template "{name}" would be created according definition.', } } else: @@ -861,7 +857,7 @@ def present(name, params, static_host_list=True, **kwargs): ret["changes"] = { name: { "old": f'Zabbix Template "{name}" did not exist.', - "new": (f'Zabbix Template "{name}" created according definition.'), + "new": f'Zabbix Template "{name}" created according definition.', } } else: @@ -871,10 +867,7 @@ def present(name, params, static_host_list=True, **kwargs): ret["changes"] = { name: { "old": f'Zabbix Template "{name}" differs.', - "new": ( - 'Zabbix Template "{}" would be updated ' - "according definition.".format(name) - ), + "new": f'Zabbix Template "{name}" would be updated according definition.', } } else: @@ -882,7 +875,7 @@ def present(name, params, static_host_list=True, **kwargs): ret["changes"] = { name: { "old": f'Zabbix Template "{name}" differed.', - "new": (f'Zabbix Template "{name}" updated according definition.'), + "new": f'Zabbix Template "{name}" updated according definition.', } } diff --git a/src/saltext/saltext_zabbix/states/zabbix_user.py b/src/saltext/zabbix/states/zabbix_user.py similarity index 99% rename from src/saltext/saltext_zabbix/states/zabbix_user.py rename to src/saltext/zabbix/states/zabbix_user.py index a34ce1b..e50a5c9 100644 --- a/src/saltext/saltext_zabbix/states/zabbix_user.py +++ b/src/saltext/zabbix/states/zabbix_user.py @@ -5,6 +5,7 @@ """ + import logging from copy import deepcopy diff --git a/src/saltext/saltext_zabbix/states/zabbix_usergroup.py b/src/saltext/zabbix/states/zabbix_usergroup.py similarity index 99% rename from src/saltext/saltext_zabbix/states/zabbix_usergroup.py rename to src/saltext/zabbix/states/zabbix_usergroup.py index 63e61d8..09bfbaf 100644 --- a/src/saltext/saltext_zabbix/states/zabbix_usergroup.py +++ b/src/saltext/zabbix/states/zabbix_usergroup.py @@ -20,7 +20,7 @@ def present(name, **kwargs): Creates new user group. NOTE: This function accepts all standard user group properties: keyword argument names differ depending on your zabbix version, see: - https://www.zabbix.com/documentation/2.0/manual/appendix/api/usergroup/definitions#user_group + https://www.zabbix.com/documentation/2.0/manual/appendix/api/usergroup/definitions#user-group .. versionadded:: 2016.3.0 diff --git a/src/saltext/saltext_zabbix/states/zabbix_usermacro.py b/src/saltext/zabbix/states/zabbix_usermacro.py similarity index 100% rename from src/saltext/saltext_zabbix/states/zabbix_usermacro.py rename to src/saltext/zabbix/states/zabbix_usermacro.py diff --git a/src/saltext/saltext_zabbix/states/zabbix_valuemap.py b/src/saltext/zabbix/states/zabbix_valuemap.py similarity index 91% rename from src/saltext/saltext_zabbix/states/zabbix_valuemap.py rename to src/saltext/zabbix/states/zabbix_valuemap.py index e53306e..931187a 100644 --- a/src/saltext/saltext_zabbix/states/zabbix_valuemap.py +++ b/src/saltext/zabbix/states/zabbix_valuemap.py @@ -5,6 +5,7 @@ :codeauthor: Jakub Sliva """ + import json import logging @@ -96,10 +97,10 @@ def present(name, params, **kwargs): ret["changes"] = { name: { "old": ( - 'Zabbix Value map "{}" differs ' - "in following parameters: {}".format(name, diff_params) + f'Zabbix Value map "{name}" differs ' + f"in following parameters: {diff_params}" ), - "new": (f'Zabbix Value map "{name}" would correspond to definition.'), + "new": f'Zabbix Value map "{name}" would correspond to definition.', } } else: @@ -116,8 +117,8 @@ def present(name, params, **kwargs): ret["changes"] = { name: { "old": ( - 'Zabbix Value map "{}" differed ' - "in following parameters: {}".format(name, diff_params) + f'Zabbix Value map "{name}" differed ' + f"in following parameters: {diff_params}" ), "new": f'Zabbix Value map "{name}" fixed.', } @@ -125,9 +126,9 @@ def present(name, params, **kwargs): else: ret["result"] = True - ret[ - "comment" - ] = f'Zabbix Value map "{name}" already exists and corresponds to a definition.' + ret["comment"] = ( + f'Zabbix Value map "{name}" already exists and corresponds to a definition.' + ) else: if dry_run: @@ -136,10 +137,7 @@ def present(name, params, **kwargs): ret["changes"] = { name: { "old": f'Zabbix Value map "{name}" does not exist.', - "new": ( - 'Zabbix Value map "{}" would be created ' - "according definition.".format(name) - ), + "new": f'Zabbix Value map "{name}" would be created according definition.', } } else: diff --git a/tests/conftest.py b/tests/conftest.py index bfeea1e..a88b645 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,19 +1,30 @@ +import logging import os -import sys import pytest -import salt.config -from saltext.saltext_zabbix import PACKAGE_ROOT -from saltfactories.utils import random_string # pylint: disable=wrong-import-order +from saltfactories.utils import random_string + +from saltext.zabbix import PACKAGE_ROOT + +# Reset the root logger to its default level(because salt changed it) +logging.root.setLevel(logging.WARNING) + + +# This swallows all logging to stdout. +# To show select logs, set --log-cli-level= +for handler in logging.root.handlers[:]: + logging.root.removeHandler(handler) + handler.close() @pytest.fixture(scope="session") def salt_factories_config(): """ - Return a dictionary with the keyworkd arguments for FactoriesManager + Return a dictionary with the keyword arguments for FactoriesManager """ return { "code_dir": str(PACKAGE_ROOT), + "inject_sitecustomize": "COVERAGE_PROCESS_START" in os.environ, "start_timeout": 120 if os.environ.get("CI") else 60, } @@ -26,86 +37,3 @@ def master(salt_factories): @pytest.fixture(scope="package") def minion(master): return master.salt_minion_daemon(random_string("minion-")) - - -@pytest.fixture(scope="session") -def integration_files_dir(salt_factories): - """ - Fixture which returns the salt integration files directory path. - Creates the directory if it does not yet exist. - """ - dirname = salt_factories.root_dir / "integration-files" - dirname.mkdir(exist_ok=True) - return dirname - - -@pytest.fixture(scope="session") -def state_tree_root_dir(integration_files_dir): - """ - Fixture which returns the salt state tree root directory path. - Creates the directory if it does not yet exist. - """ - dirname = integration_files_dir / "state-tree" - dirname.mkdir(exist_ok=True) - return dirname - - -@pytest.fixture(scope="session") -def base_env_state_tree_root_dir(state_tree_root_dir): - """ - Fixture which returns the salt base environment state tree directory path. - Creates the directory if it does not yet exist. - """ - dirname = state_tree_root_dir / "base" - dirname.mkdir(exist_ok=True) - return dirname - - -@pytest.fixture -def minion_opts(tmp_path): - """ - Default minion configuration with relative temporary paths to not require root permissions. - """ - root_dir = tmp_path / "minion" - opts = salt.config.DEFAULT_MINION_OPTS.copy() - opts["__role"] = "minion" - opts["root_dir"] = str(root_dir) - for name in ("cachedir", "pki_dir", "sock_dir", "conf_dir"): - dirpath = root_dir / name - dirpath.mkdir(parents=True) - opts[name] = str(dirpath) - opts["log_file"] = "logs/minion.log" - return opts - - -@pytest.fixture -def master_opts(tmp_path): - """ - Default master configuration with relative temporary paths to not require root permissions. - """ - root_dir = tmp_path / "master" - opts = salt.config.DEFAULT_MASTER_OPTS.copy() - opts["__role"] = "master" - opts["root_dir"] = str(root_dir) - for name in ("cachedir", "pki_dir", "sock_dir", "conf_dir"): - dirpath = root_dir / name - dirpath.mkdir(parents=True) - opts[name] = str(dirpath) - opts["log_file"] = "logs/master.log" - return opts - - -@pytest.fixture -def perm_denied_error_log(): - if sys.platform.startswith("win32"): - perm_denied_error_log = ( - "Unable to create directory " - "C:\\ProgramData\\Salt Project\\Salt\\srv\\salt\\minion. " - "Check that the salt user has the correct permissions." - ) - else: - perm_denied_error_log = ( - "Unable to create directory /srv/salt/minion. " - "Check that the salt user has the correct permissions." - ) - return perm_denied_error_log diff --git a/tests/functional/__init__.py b/tests/functional/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/functional/conftest.py b/tests/functional/conftest.py new file mode 100644 index 0000000..2c7c84a --- /dev/null +++ b/tests/functional/conftest.py @@ -0,0 +1,150 @@ +import logging +import shutil + +import pytest +from saltfactories.utils.functional import Loaders + +log = logging.getLogger(__name__) + + +@pytest.fixture(scope="package") +def minion_id(): + return "func-tests-minion-opts" + + +@pytest.fixture(scope="module") +def state_tree(tmp_path_factory): + state_tree_path = tmp_path_factory.mktemp("state-tree-base") + try: + yield state_tree_path + finally: + shutil.rmtree(str(state_tree_path), ignore_errors=True) + + +@pytest.fixture(scope="module") +def state_tree_prod(tmp_path_factory): + state_tree_path = tmp_path_factory.mktemp("state-tree-prod") + try: + yield state_tree_path + finally: + shutil.rmtree(str(state_tree_path), ignore_errors=True) + + +@pytest.fixture(scope="module") +def minion_config_defaults(): + """ + Functional test modules can provide this fixture to tweak the default + configuration dictionary passed to the minion factory + """ + return {} + + +@pytest.fixture(scope="module") +def minion_config_overrides(): + """ + Functional test modules can provide this fixture to tweak the configuration + overrides dictionary passed to the minion factory + """ + return {} + + +@pytest.fixture(scope="module") +def minion_opts( + salt_factories, + minion_id, + state_tree, + state_tree_prod, + minion_config_defaults, + minion_config_overrides, +): + minion_config_overrides.update( + { + "file_client": "local", + "file_roots": { + "base": [ + str(state_tree), + ], + "prod": [ + str(state_tree_prod), + ], + }, + } + ) + factory = salt_factories.salt_minion_daemon( + minion_id, + defaults=minion_config_defaults or None, + overrides=minion_config_overrides, + ) + return factory.config.copy() + + +@pytest.fixture(scope="module") +def master_config_defaults(): + """ + Functional test modules can provide this fixture to tweak the default + configuration dictionary passed to the master factory + """ + return {} + + +@pytest.fixture(scope="module") +def master_config_overrides(): + """ + Functional test modules can provide this fixture to tweak the configuration + overrides dictionary passed to the master factory + """ + return {} + + +@pytest.fixture(scope="module") +def master_opts( + salt_factories, + state_tree, + state_tree_prod, + master_config_defaults, + master_config_overrides, +): + master_config_overrides.update( + { + "file_client": "local", + "file_roots": { + "base": [ + str(state_tree), + ], + "prod": [ + str(state_tree_prod), + ], + }, + } + ) + factory = salt_factories.salt_master_daemon( + "func-tests-master-opts", + defaults=master_config_defaults or None, + overrides=master_config_overrides, + ) + return factory.config.copy() + + +@pytest.fixture(scope="module") +def loaders(minion_opts): + return Loaders(minion_opts, loaded_base_name=f"{__name__}.loaded") + + +@pytest.fixture(autouse=True) +def reset_loaders_state(loaders): + try: + # Run the tests + yield + finally: + # Reset the loaders state + loaders.reset_state() + + +@pytest.fixture(scope="module") +def modules(loaders): + return loaders.modules + + +@pytest.fixture(scope="module") +def states(loaders): + return loaders.states diff --git a/tests/functional/modules/__init__.py b/tests/functional/modules/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/functional/returners/__init__.py b/tests/functional/returners/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/functional/states/__init__.py b/tests/functional/states/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/integration/modules/__init__.py b/tests/integration/modules/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/integration/returners/__init__.py b/tests/integration/returners/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/integration/states/__init__.py b/tests/integration/states/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py new file mode 100644 index 0000000..b3b6ced --- /dev/null +++ b/tests/unit/conftest.py @@ -0,0 +1,62 @@ +import os + +import pytest +import salt.config + + +@pytest.fixture +def minion_opts(tmp_path): + """ + Default minion configuration with relative temporary paths to not + require root permissions. + """ + root_dir = tmp_path / "minion" + opts = salt.config.DEFAULT_MINION_OPTS.copy() + opts["__role"] = "minion" + opts["root_dir"] = str(root_dir) + for name in ("cachedir", "pki_dir", "sock_dir", "conf_dir"): + dirpath = root_dir / name + dirpath.mkdir(parents=True) + opts[name] = str(dirpath) + opts["log_file"] = "logs/minion.log" + opts["conf_file"] = os.path.join(opts["conf_dir"], "minion") + return opts + + +@pytest.fixture +def master_opts(tmp_path): + """ + Default master configuration with relative temporary paths to not + require root permissions. + """ + root_dir = tmp_path / "master" + opts = salt.config.master_config(None) + opts["__role"] = "master" + opts["root_dir"] = str(root_dir) + for name in ("cachedir", "pki_dir", "sock_dir", "conf_dir"): + dirpath = root_dir / name + dirpath.mkdir(parents=True) + opts[name] = str(dirpath) + opts["log_file"] = "logs/master.log" + opts["conf_file"] = os.path.join(opts["conf_dir"], "master") + return opts + + +@pytest.fixture +def syndic_opts(tmp_path): + """ + Default master configuration with relative temporary paths to not + require root permissions. + """ + root_dir = tmp_path / "syndic" + opts = salt.config.DEFAULT_MINION_OPTS.copy() + opts["syndic_master"] = "127.0.0.1" + opts["__role"] = "minion" + opts["root_dir"] = str(root_dir) + for name in ("cachedir", "pki_dir", "sock_dir", "conf_dir"): + dirpath = root_dir / name + dirpath.mkdir(parents=True) + opts[name] = str(dirpath) + opts["log_file"] = "logs/syndic.log" + opts["conf_file"] = os.path.join(opts["conf_dir"], "syndic") + return opts diff --git a/tests/unit/modules/__init__.py b/tests/unit/modules/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/modules/test_zabbix.py b/tests/unit/modules/test_zabbix.py index 159dec9..de235cd 100644 --- a/tests/unit/modules/test_zabbix.py +++ b/tests/unit/modules/test_zabbix.py @@ -2,13 +2,15 @@ Tests for salt.modules.zabbix :codeauthor: Jerzy Drozdz """ + from unittest.mock import patch import pytest import salt.modules.config as config -import saltext.saltext_zabbix.modules.zabbix as zabbix from salt.exceptions import SaltException +import saltext.zabbix.modules.zabbix as zabbix + GETID_QUERY_RESULT_OK = [{"internal": "0", "flags": "0", "groupid": "11", "name": "Databases"}] GETID_QUERY_RESULT_BAD = [ {"internal": "0", "flags": "0", "groupid": "11", "name": "Databases"}, diff --git a/tests/unit/returners/__init__.py b/tests/unit/returners/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/states/__init__.py b/tests/unit/states/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/states/zabbix/test_action.py b/tests/unit/states/zabbix/test_action.py index 65bede0..e277139 100644 --- a/tests/unit/states/zabbix/test_action.py +++ b/tests/unit/states/zabbix/test_action.py @@ -1,11 +1,13 @@ """ :codeauthor: :email:`Jakub Sliva ` """ + from unittest.mock import MagicMock from unittest.mock import patch import pytest -import saltext.saltext_zabbix.states.zabbix_action as zabbix_action + +import saltext.zabbix.states.zabbix_action as zabbix_action @pytest.fixture @@ -179,9 +181,9 @@ def test_present_exists(input_params, existing_obj): }, ): ret["result"] = True - ret[ - "comment" - ] = f'Zabbix Action "{name}" already exists and corresponds to a definition.' + ret["comment"] = ( + f'Zabbix Action "{name}" already exists and corresponds to a definition.' + ) assert zabbix_action.present(name, {}) == ret diff --git a/tests/unit/states/zabbix/test_host.py b/tests/unit/states/zabbix/test_host.py index 7ea403b..8f8b406 100644 --- a/tests/unit/states/zabbix/test_host.py +++ b/tests/unit/states/zabbix/test_host.py @@ -1,13 +1,15 @@ """ :codeauthor: Piter Punk """ + import ast from collections import OrderedDict from unittest.mock import MagicMock from unittest.mock import patch import pytest -import saltext.saltext_zabbix.states.zabbix_host as zabbix_host + +import saltext.zabbix.states.zabbix_host as zabbix_host @pytest.fixture diff --git a/tests/unit/states/zabbix/test_template.py b/tests/unit/states/zabbix/test_template.py index ed601f2..ff270c5 100644 --- a/tests/unit/states/zabbix/test_template.py +++ b/tests/unit/states/zabbix/test_template.py @@ -1,11 +1,13 @@ """ :codeauthor: :email:`Jakub Sliva ` """ + from unittest.mock import MagicMock from unittest.mock import patch import pytest -import saltext.saltext_zabbix.states.zabbix_template as zabbix_template + +import saltext.zabbix.states.zabbix_template as zabbix_template @pytest.fixture diff --git a/tests/unit/states/zabbix/test_valuemap.py b/tests/unit/states/zabbix/test_valuemap.py index 839bcaf..125b482 100644 --- a/tests/unit/states/zabbix/test_valuemap.py +++ b/tests/unit/states/zabbix/test_valuemap.py @@ -1,12 +1,14 @@ """ :codeauthor: :email:`Jakub Sliva ` """ + from unittest.mock import MagicMock from unittest.mock import patch import pytest import salt.states.zabbix_valuemap as zabbix_valuemap -import saltext.saltext_zabbix.states.zabbix_valuemap as zabbix_valuemap + +import saltext.zabbix.states.zabbix_valuemap as zabbix_valuemap @pytest.fixture @@ -118,9 +120,9 @@ def test_present_exists(input_params, existing_obj): }, ): ret["result"] = True - ret[ - "comment" - ] = f'Zabbix Value map "{name}" already exists and corresponds to a definition.' + ret["comment"] = ( + f'Zabbix Value map "{name}" already exists and corresponds to a definition.' + ) assert zabbix_valuemap.present(name, {}) == ret