diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..7ba5b94 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,70 @@ +--- +name: Bug Report +about: Report a reproducible bug to help us improve JSNAPy +title: "[BUG] " +labels: bug +assignees: '' +--- + +## Description +A clear and concise description of the bug. + +## Steps to Reproduce +1. +2. +3. + +## Expected Behavior +What you expected to happen. + +## Actual Behavior +What actually happened. Include any error messages or stack traces. + +``` + +``` + +## Environment + +| Item | Details | +|------------------|---------| +| JSNAPy version (`jsnapy --version`) | | +| Python version | | +| Operating System | | +| Junos OS version | | +| Device model | | +| Install method | pip / source / Docker | + +## Configuration Files + +
+JSNAPy config YAML (redact credentials) + +```yaml + +``` +
+ +
+Test YAML file + +```yaml + +``` +
+ +
+Snapshot XML (if relevant) + +```xml + +``` +
+ +## Additional Context +Add any other context, screenshots, or links to related issues here. + +## Checklist +- [ ] I searched [existing issues](https://github.com/Juniper/jsnapy/issues) and this is not a duplicate +- [ ] I reproduced the issue on the latest release or `master` branch +- [ ] I have included all relevant config/test files (with credentials redacted) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..37e505e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,11 @@ +blank_issues_enabled: false +contact_links: + - name: Report a Security Vulnerability + url: https://github.com/Juniper/jsnapy/security/advisories/new + about: Please report security vulnerabilities privately. Do NOT open a public issue for security bugs. + - name: JSNAPy Wiki & Documentation + url: https://github.com/Juniper/jsnapy/wiki + about: Check the wiki before opening an issue — your question may already be answered. + - name: GitHub Community Support + url: https://github.com/orgs/community/discussions + about: For general GitHub usage questions, ask the community here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..ce7e21f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,34 @@ +--- +name: Feature Request +about: Suggest a new feature or enhancement for JSNAPy +title: "[FEATURE] " +labels: enhancement +assignees: '' +--- + +## Summary +A clear and concise description of the feature you are requesting. + +## Problem / Motivation +Describe the problem this feature would solve, or the use case that motivates the request. +_(e.g. "I find it difficult to ... when ...")_ + +## Proposed Solution +Describe the solution you'd like. Include any new YAML keys, CLI flags, Python API changes, or behaviour you envision. + +```yaml +# Example config / usage snippet (if applicable) +``` + +## Alternatives Considered +List any alternative solutions or workarounds you have already tried or considered, and why they are insufficient. + +## Additional Context +- Links to related issues, PRs, or discussions +- Reference to relevant Junos RPC / operational commands (if applicable) +- Any other context or screenshots + +## Checklist +- [ ] I searched [existing issues](https://github.com/Juniper/jsnapy/issues) and this is not already requested +- [ ] I checked the [JSNAPy wiki](https://github.com/Juniper/jsnapy/wiki) and this is not already supported +- [ ] I am willing to submit a pull request to implement this feature diff --git a/.github/ISSUE_TEMPLATE/task.md b/.github/ISSUE_TEMPLATE/task.md new file mode 100644 index 0000000..1ef19cd --- /dev/null +++ b/.github/ISSUE_TEMPLATE/task.md @@ -0,0 +1,40 @@ +--- +name: Task +about: Describe a task, chore, or maintenance work to be done in JSNAPy +title: "[TASK] " +labels: task +assignees: '' +--- + +## Summary +A clear and concise description of the task to be completed. + +## Background / Motivation +Explain why this task is needed (e.g. technical debt, CI improvement, dependency upgrade, documentation update). + +## Acceptance Criteria +List the specific conditions that must be met for this task to be considered done. + +- [ ] +- [ ] +- [ ] + +## Implementation Notes +Any technical details, constraints, or approach suggestions relevant to completing the task. + +## Sub-tasks +Break down the work into smaller steps if applicable. + +- [ ] +- [ ] + +## Related Issues / PRs +Link any related issues, pull requests, or discussions. + +## Additional Context +Add any other context, references, or screenshots here. + +## Checklist +- [ ] I searched [existing issues](https://github.com/Juniper/jsnapy/issues) and this task is not already tracked +- [ ] Acceptance criteria are clearly defined above +- [ ] I am willing to submit a pull request for this task diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..171da29 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,84 @@ +## Description + + + +Closes # + +## Type of Change + + + +- [ ] Bug fix (non-breaking change that fixes an issue) +- [ ] Feature / Enhancement (non-breaking change that adds functionality) +- [ ] Task / Chore (refactor, dependency update, CI, docs, etc.) +- [ ] Breaking change (fix or feature that would cause existing functionality to change) + +## Changes Made + + + +- +- +- + +--- + +## Checklist + +### Code Quality + +- [ ] Code follows the project's style guidelines +- [ ] `pylint` reports no new errors or warnings (run against changed files under `lib/jnpr/jsnapy/`) + + ```bash + sudo find ./lib/jnpr/jsnapy -type f -name "*.py" | xargs pylint | grep . + ``` + +- [ ] `black` formatting check passes + + ```bash + black --check --diff --exclude="docs|build|tests|samples|venv" . + ``` + +### Unit Tests + +- [ ] New or updated unit tests have been added under `tests/unit/` +- [ ] All unit tests pass locally + + ```bash + cd tests/unit + nose2 --with-coverage -vvvv + ``` + +- [ ] Code coverage has not decreased + +### Documentation + +- [ ] YAML samples in `samples/` updated or added where applicable +- [ ] `README.md` or wiki references updated (if behaviour changed) + +### General + +- [ ] No hardcoded credentials, IPs, or sensitive data introduced +- [ ] `requirements.txt` / `development.txt` updated (if new packages were added) +- [ ] I have read [CONTRIBUTING.md](../CONTRIBUTING.md) and my contribution complies with the Apache 2.0 License + +--- + +## Testing Matrix + + + +| Python | OS | Pylint | Black | Unit Tests | +|---------|---------------|--------|-------|------------| +| 3.8.x | ubuntu-latest | [ ] | [ ] | [ ] | +| 3.9.x | ubuntu-latest | [ ] | [ ] | [ ] | +| 3.10.x | ubuntu-latest | [ ] | [ ] | [ ] | +| 3.11.x | ubuntu-latest | [ ] | [ ] | [ ] | +| 3.12.x | ubuntu-latest | [ ] | [ ] | [ ] | + +--- + +## Additional Notes + + diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 0000000..909999c --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,14 @@ +# Security Policy + +## Supported Versions + +Only the latest stable version of JSNAPy receives security updates. Make sure you are running the most recent release. + +## Reporting a Vulnerability + +Please do not open public issues for security problems. Instead, use GitHub's "Report a vulnerability" feature in the Security tab of this repository. We will review and respond as soon as possible. + +## Security Updates + +If we fix a vulnerability, we will announce it in the release notes. Keep your installation up to date to receive the latest fixes. + diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml index d3aac67..711c9b4 100644 --- a/.github/workflows/pylint.yml +++ b/.github/workflows/pylint.yml @@ -17,9 +17,9 @@ jobs: python-version: [3.8.12, 3.9.12, 3.10.12, 3.11.9, 3.12.4] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Validate version @@ -46,7 +46,7 @@ jobs: cd ../ tar -xzvf jsnapy-*.tar.gz cd jsnapy-1.3.8 - python setup.py install + pip install . - name: Analysing the code with pylint @@ -56,7 +56,7 @@ jobs: - name: Run black tool run: | - pip install -U black; + pip install black==24.8.0; black --check --diff --exclude="docs|build|tests|samples|venv" . - name: Run unit test diff --git a/development.txt b/development.txt index 479f8b1..c9d8953 100644 --- a/development.txt +++ b/development.txt @@ -1,5 +1,6 @@ -r requirements.txt +black==24.8.0 # pinned: last version supporting Python 3.8 (24.10.0 requires >=3.9) coverage # http://nedbatchelder.com/code/coverage/ mock==1.0.1 # http://www.voidspace.org.uk/python/mock/ nose # http://nose.readthedocs.org/en/latest/ diff --git a/lib/jnpr/jsnapy/check.py b/lib/jnpr/jsnapy/check.py index 80918b0..42abf83 100755 --- a/lib/jnpr/jsnapy/check.py +++ b/lib/jnpr/jsnapy/check.py @@ -245,7 +245,7 @@ def expression_evaluator( # default error and info message err_mssg = self.get_err_mssg(elem_test, ele_list) info_mssg = self.get_info_mssg(elem_test, ele_list) - ignore_null = elem_test.get("ignore-null") or top_ignore_null + ignore_null = elem_test.get("ignore-null", top_ignore_null) # check test operators, below mentioned four are allowed only # with --check #### is_skipped = False diff --git a/lib/jnpr/jsnapy/jsnapy.py b/lib/jnpr/jsnapy/jsnapy.py index 75ee488..70af893 100755 --- a/lib/jnpr/jsnapy/jsnapy.py +++ b/lib/jnpr/jsnapy/jsnapy.py @@ -426,7 +426,7 @@ def compare_tests( pre_snap=None, post_snap=None, action=None, - **kwargs + **kwargs, ): """ called by check and snapcheck argument, to compare snap files @@ -617,7 +617,7 @@ def connect( config_data=None, action=None, post_snap=None, - **kwargs + **kwargs, ): """ connect to device and calls the function either to generate snapshots @@ -661,7 +661,7 @@ def connect( user=username, passwd=password, gather_facts=False, - **kwargs + **kwargs, ) try: dev.open() @@ -678,7 +678,7 @@ def connect( config_data, action, post_snap, - **kwargs + **kwargs, ) else: self.logger.error( @@ -996,7 +996,7 @@ def check_arguments(self): # then it should print error message. if not ( (self.args.file is None) - and ((self.args.testfiles is None or self.args.hostname is None)) + and (self.args.testfiles is None or self.args.hostname is None) ): action = None if self.set_action_cmd(action) is not None: diff --git a/lib/jnpr/jsnapy/operator.py b/lib/jnpr/jsnapy/operator.py index 156a707..3d74a5d 100755 --- a/lib/jnpr/jsnapy/operator.py +++ b/lib/jnpr/jsnapy/operator.py @@ -54,7 +54,7 @@ def define_operator( iter, id, test_name, - *args + *args, ): """ It will call functions according to test operator @@ -82,7 +82,7 @@ def define_operator( iter, id, test_name, - *args + *args, ) except AttributeError as e: self.logger_testop.error( diff --git a/requirements.txt b/requirements.txt index 0034a92..0ed62e6 100755 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +setuptools colorama configparser pyparsing diff --git a/setup.py b/setup.py index 465da77..86f561b 100755 --- a/setup.py +++ b/setup.py @@ -47,7 +47,7 @@ def set_logging_path(path): ) elif "win32" in sys.platform: value["filename"] = os.path.join( - os.path.expanduser("~"), "logs\jsnapy\jsnapy.log" + os.path.expanduser("~"), "logs", "jsnapy", "jsnapy.log" ) with open(path, "w") as dump_f: