From d37e3077945515234872deebde62190a79121449 Mon Sep 17 00:00:00 2001 From: "Baczek, Arkadiusz" Date: Wed, 9 Jul 2025 11:55:24 +0200 Subject: [PATCH] feat: Initial commit Signed-off-by: Baczek, Arkadiusz --- .github/workflows/build_upload_whl.yml | 205 +++++++++++++++ .github/workflows/codeql.yml | 98 ++++++++ .github/workflows/manual_release.yml | 33 +++ .github/workflows/pull_requests.yml | 29 +++ .gitignore | 237 ++++++++++++++++++ AUTHORS.md | 7 + CODE_OF_CONDUCT.md | 2 +- CONTRIBUTING.md | 4 +- LICENSE.md | 8 + README.md | 38 +++ examples/simple_example.py | 19 ++ mfd_kernel_namespace/__init__.py | 5 + mfd_kernel_namespace/exceptions.py | 3 + mfd_kernel_namespace/network_namespace.py | 22 ++ pyproject.toml | 27 ++ requirements-dev.txt | 5 + requirements-docs.txt | 3 + requirements-test.txt | 7 + requirements.txt | 2 + sphinx-doc/Makefile | 20 ++ sphinx-doc/README.md | 13 + sphinx-doc/conf.py | 165 ++++++++++++ sphinx-doc/generate_docs.py | 18 ++ sphinx-doc/genindex.rst | 4 + sphinx-doc/index.rst | 21 ++ sphinx-doc/py-modindex.rst | 4 + tests/__init__.py | 2 + tests/unit/__init__.py | 2 + .../test_mfd_kernel_namespace/__init__.py | 2 + .../test_mfd_kernel_namespace.py | 15 ++ 30 files changed, 1017 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/build_upload_whl.yml create mode 100644 .github/workflows/codeql.yml create mode 100644 .github/workflows/manual_release.yml create mode 100644 .github/workflows/pull_requests.yml create mode 100644 .gitignore create mode 100644 AUTHORS.md create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 examples/simple_example.py create mode 100644 mfd_kernel_namespace/__init__.py create mode 100644 mfd_kernel_namespace/exceptions.py create mode 100644 mfd_kernel_namespace/network_namespace.py create mode 100644 pyproject.toml create mode 100644 requirements-dev.txt create mode 100644 requirements-docs.txt create mode 100644 requirements-test.txt create mode 100644 requirements.txt create mode 100644 sphinx-doc/Makefile create mode 100644 sphinx-doc/README.md create mode 100644 sphinx-doc/conf.py create mode 100644 sphinx-doc/generate_docs.py create mode 100644 sphinx-doc/genindex.rst create mode 100644 sphinx-doc/index.rst create mode 100644 sphinx-doc/py-modindex.rst create mode 100644 tests/__init__.py create mode 100644 tests/unit/__init__.py create mode 100644 tests/unit/test_mfd_kernel_namespace/__init__.py create mode 100644 tests/unit/test_mfd_kernel_namespace/test_mfd_kernel_namespace.py diff --git a/.github/workflows/build_upload_whl.yml b/.github/workflows/build_upload_whl.yml new file mode 100644 index 0000000..38fec87 --- /dev/null +++ b/.github/workflows/build_upload_whl.yml @@ -0,0 +1,205 @@ +name: CI Build Reusable Workflow +on: + workflow_call: + secrets: + GH_TOKEN: + description: 'GitHub token for authentication' + required: true + PYPI_TOKEN: + description: 'PyPI API token to publish package' + required: false + inputs: + UPLOAD_PACKAGE: + description: 'Should the package be uploaded to PyPI?' + required: false + default: false + type: boolean + REPOSITORY_NAME: + description: 'Repository name' + required: false + type: string + BRANCH_NAME: + description: 'Branch name to checkout' + required: true + type: string + PYTHON_VERSION: + description: 'Python version to use' + required: false + default: '3.10.11' + type: string + PUSH_TAG: + description: 'Push tag after version bump' + required: false + default: false + type: boolean + RELEASE_BUILD: + description: 'Is release build?' + required: false + default: false + type: boolean + GIT_USER: + description: 'Git user name for commit and tag' + required: true + type: string + GIT_EMAIL: + description: 'Git user email for commit and tag' + required: true + type: string + PROJECT_NAME: + description: 'Project name for tests' + required: true + type: string + SOURCE_PATH: + description: 'Path to the source code directory' + required: false + default: 'src' + type: string + RUNS_ON: + description: 'Runner type for the job' + required: false + default: 'ubuntu-latest' + type: string + +jobs: + build_whl: + permissions: + contents: write + id-token: write + environment: + name: "pypi" + url: https://pypi.org/p/${{ inputs.PROJECT_NAME }} + runs-on: ${{ inputs.RUNS_ON }} + steps: + - uses: actions/checkout@v4 + with: + fetch-tags: true + fetch-depth: 0 + path: ${{ inputs.SOURCE_PATH }} + ref: ${{ inputs.BRANCH_NAME }} + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{ inputs.PYTHON_VERSION }} + cache: 'pip' + + - name: Version bumping + id: VERSION_BUMP + if: inputs.RELEASE_BUILD == true + env: + GIT_AUTHOR_NAME: ${{ inputs.GIT_USER }} + GIT_AUTHOR_EMAIL: ${{ inputs.GIT_EMAIL }} + GIT_COMMITTER_NAME: ${{ inputs.GIT_USER }} + GIT_COMMITTER_EMAIL: ${{ inputs.GIT_EMAIL }} + shell: bash + run: | + python -m pip install --upgrade pip + python -m venv bump_version + source bump_version/bin/activate + pip install python-semantic-release~=10.2 + pip install -r ${{ inputs.SOURCE_PATH }}/requirements-dev.txt + mfd-create-config-files --project-dir ./${{ inputs.SOURCE_PATH }} + cd ${{ inputs.SOURCE_PATH }} + version_after_bump=$(semantic-release version --print | tail -n 1 | tr -d '\n') + version_from_tag=$(git describe --tags --abbrev=0 | tr -d '\n' | sed 's/^v//') + echo "Version after semantic-release bump is: ${version_after_bump}" + echo "Version from tag: ${version_from_tag}" + # Only check version equality if RELEASE_BUILD is true + if [ "${{ inputs.RELEASE_BUILD }}" == "true" ]; then + if [ "$version_after_bump" == "$version_from_tag" ]; then + echo "Version would not change: version_after_bump=${version_after_bump}, version_from_tag=${version_from_tag}" + exit 1 + fi + fi + semantic-release version --no-push --no-vcs-release + cat pyproject.toml + echo "version_after_bump=v${version_after_bump}" >> $GITHUB_OUTPUT + - name: Create virtual environment for whl creation + shell: bash + run: | + python -m venv whl_creation + source whl_creation/bin/activate + pip install build==1.2.2.post1 + cd ${{ inputs.SOURCE_PATH }} + ../whl_creation/bin/python -m build --wheel --outdir ../whl_creation/dist + ls -l ../whl_creation/dist + + - name: Determine if unit and functional tests should run + id: test_check + shell: bash + run: | + REPO_NAME=$(echo "${{ inputs.PROJECT_NAME }}") + echo "Repository name extracted: $REPO_NAME" + + UNIT_TEST_DIR="${{ inputs.SOURCE_PATH }}/tests/unit/test_$(echo "${REPO_NAME}" | tr '-' '_')" + FUNC_TEST_DIR="${{ inputs.SOURCE_PATH }}/tests/system/test_$(echo "${REPO_NAME}" | tr '-' '_')" + if [ -d "$UNIT_TEST_DIR" ]; then + echo "Unit tests directory exists: $UNIT_TEST_DIR" + echo "run_unit_tests=true" >> $GITHUB_OUTPUT + else + echo "Unit tests directory does not exist: $UNIT_TEST_DIR" + echo "run_unit_tests=false" >> $GITHUB_OUTPUT + fi + if [ -d "$FUNC_TEST_DIR" ]; then + echo "Functional tests directory exists: $FUNC_TEST_DIR" + echo "run_functional_tests=true" >> $GITHUB_OUTPUT + else + echo "Functional tests directory does not exist: $FUNC_TEST_DIR" + echo "run_functional_tests=false" >> $GITHUB_OUTPUT + fi + + - name: Install dependencies for tests + if: steps.test_check.outputs.run_unit_tests == 'true' || steps.test_check.outputs.run_functional_tests == 'true' + shell: bash + run: | + python -m venv test_env + source test_env/bin/activate + python -m pip install -r "${{ inputs.SOURCE_PATH }}/requirements.txt" -r "${{ inputs.SOURCE_PATH }}/requirements-test.txt" -r "${{ inputs.SOURCE_PATH }}/requirements-dev.txt" + + - name: Run unit tests if test directory exists + if: steps.test_check.outputs.run_unit_tests == 'true' + shell: bash + run: | + source test_env/bin/activate + mfd-unit-tests --project-dir ${{ github.workspace }}/${{ inputs.SOURCE_PATH }} + + - name: Run functional tests if test directory exists + if: steps.test_check.outputs.run_functional_tests == 'true' + shell: bash + run: | + source test_env/bin/activate + mfd-system-tests --project-dir ${{ github.workspace }}/${{ inputs.SOURCE_PATH }} + - name: Publish package distributions to PyPI + if: ${{ inputs.RELEASE_BUILD == true && inputs.UPLOAD_PACKAGE == true }} + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: 'whl_creation/dist' + password: ${{ secrets.PYPI_TOKEN }} + + - name: Publish comment how to build .whl + if: inputs.RELEASE_BUILD == false + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GH_TOKEN }} + script: | + const prNumber = context.payload.pull_request.number; + const commentBody = "We don't publish DEVs .whl.\n To build .whl, run 'pip install git+https://github.com/${{ inputs.REPOSITORY_NAME }}@${{ inputs.BRANCH_NAME }}'"; + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: commentBody + }); + + - name: Push git tag after version bump + if: ${{ inputs.RELEASE_BUILD == true && inputs.PUSH_TAG == true }} + shell: bash + env: + GIT_AUTHOR_NAME: ${{ inputs.GIT_USER }} + GIT_AUTHOR_EMAIL: ${{ inputs.GIT_EMAIL }} + GIT_COMMITTER_NAME: ${{ inputs.GIT_USER }} + GIT_COMMITTER_EMAIL: ${{ inputs.GIT_EMAIL }} + version_after_bump: ${{ steps.VERSION_BUMP.outputs.version_after_bump }} + run: | + cd ${{ inputs.SOURCE_PATH }} + git push origin "${version_after_bump}" \ No newline at end of file diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..4c43daf --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,98 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL Advanced" + +on: + pull_request: + branches: [ "main" ] + push: + branches: [ "main" ] + +jobs: + analyze: + name: Analyze (${{ matrix.language }}) + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners (GitHub.com only) + # Consider using larger runners or machines with greater resources for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + permissions: + # required for all workflows + security-events: write + + # required to fetch internal or private CodeQL packs + packages: read + + # only required for workflows in private repositories + actions: read + contents: read + + strategy: + fail-fast: false + matrix: + include: + - language: actions + build-mode: none + - language: python + build-mode: none + # CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift' + # Use `c-cpp` to analyze code written in C, C++ or both + # Use 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, + # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. + # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how + # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Add any setup steps before running the `github/codeql-action/init` action. + # This includes steps like installing compilers or runtimes (`actions/setup-node` + # or others). This is typically only required for manual builds. + # - name: Setup runtime (example) + # uses: actions/setup-example@v1 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + # If the analyze step fails for one of the languages you are analyzing with + # "We were unable to automatically build your code", modify the matrix above + # to set the build mode to "manual" for that language. Then modify this step + # to build your code. + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + - if: matrix.build-mode == 'manual' + shell: bash + run: | + echo 'If you are using a "manual" build mode for one or more of the' \ + 'languages you are analyzing, replace this with the commands to build' \ + 'your code, for example:' + echo ' make bootstrap' + echo ' make release' + exit 1 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/manual_release.yml b/.github/workflows/manual_release.yml new file mode 100644 index 0000000..12e65ec --- /dev/null +++ b/.github/workflows/manual_release.yml @@ -0,0 +1,33 @@ +name: CI BUILD - RELEASE MODE +on: + workflow_dispatch: + +jobs: + build_upload_whl: + strategy: + matrix: + include: + - name: python-version-3-10 + python_version: '3.10' + push_tag: false + upload_package: false + continue-on-error: true + - name: python-version-3-13 + python_version: '3.13' + push_tag: true + upload_package: true + continue-on-error: true + uses: ./.github/workflows/build_upload_whl.yml + secrets: + GH_TOKEN: ${{ secrets.GH_TOKEN }} + PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} + with: + REPOSITORY_NAME: ${{ github.repository }} + BRANCH_NAME: ${{ github.ref_name }} + PYTHON_VERSION: ${{ matrix.python_version }} + PUSH_TAG: ${{ matrix.push_tag }} + RELEASE_BUILD: true + UPLOAD_PACKAGE: ${{ matrix.upload_package }} + GIT_USER: 'mfd-intel-bot' + GIT_EMAIL: 'mfd_intel_bot@intel.com' + PROJECT_NAME: 'mfd-kernel-namespace' \ No newline at end of file diff --git a/.github/workflows/pull_requests.yml b/.github/workflows/pull_requests.yml new file mode 100644 index 0000000..f1d6e08 --- /dev/null +++ b/.github/workflows/pull_requests.yml @@ -0,0 +1,29 @@ +name: DEV BUILD + +on: + pull_request: + types: [opened, synchronize] + +jobs: + build_upload_whl: + strategy: + matrix: + include: + - name: python-version-3-10 + python_version: '3.10' + push_tag: false + - name: python-version-3-13 + python_version: '3.13' + push_tag: false + uses: ./.github/workflows/build_upload_whl.yml + secrets: + GH_TOKEN: ${{ secrets.GH_TOKEN }} + with: + REPOSITORY_NAME: ${{ github.repository }} + BRANCH_NAME: ${{ github.head_ref }} + PYTHON_VERSION: ${{ matrix.python_version }} + PUSH_TAG: ${{ matrix.push_tag }} + RELEASE_BUILD: false + GIT_USER: 'mfd-intel-bot' + GIT_EMAIL: 'mfd_intel_bot@intel.com' + PROJECT_NAME: 'mfd-kernel-namespace' \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e5e4b06 --- /dev/null +++ b/.gitignore @@ -0,0 +1,237 @@ + +# Created by https://www.toptal.com/developers/gitignore/api/pycharm+all,python +# Edit at https://www.toptal.com/developers/gitignore?templates=pycharm+all,python + +### PyCharm+all ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### PyCharm+all Patch ### +# Ignores the whole .idea folder and all .iml files +# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 + +.idea/ + +# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 + +*.iml +modules.xml +.idea/misc.xml +*.ipr + +# Sonarlint plugin +.idea/sonarlint + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +coverage.json +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +pytestdebug.log + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ +doc/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +pythonenv* + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# profiling data +.prof + +# End of https://www.toptal.com/developers/gitignore/api/pycharm+all,python +ruff.toml +.pre-commit-config.yaml \ No newline at end of file diff --git a/AUTHORS.md b/AUTHORS.md new file mode 100644 index 0000000..2c515bb --- /dev/null +++ b/AUTHORS.md @@ -0,0 +1,7 @@ +# AUTHORS + +* Arkadiusz Baczek (arkadiusz.baczek@intel.com) +* Mateusz Chrominski (mateusz.chrominski@intel.com) +* Hubert Cymerys (hubert.cymerys@intel.com) +* Agnieszka Flizikowska (agnieszka.flizikowska@intel.com) +* Adrian Lasota (adrian.lasota@intel.com) \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 134f4b2..0f3a971 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -129,4 +129,4 @@ For answers to common questions about this code of conduct, see the FAQ at [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html [Mozilla CoC]: https://github.com/mozilla/diversity [FAQ]: https://www.contributor-covenant.org/faq -[translations]: https://www.contributor-covenant.org/translations +[translations]: https://www.contributor-covenant.org/translations \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f682f4e..b7eae89 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ ### License - is licensed under the terms in [LICENSE]. By contributing to the project, you agree to the license and copyright terms therein and release your contribution under these terms. +MFD Kernel Namespace is licensed under the terms in [LICENSE](LICENSE.md). By contributing to the project, you agree to the license and copyright terms therein and release your contribution under these terms. ### Sign your work @@ -54,4 +54,4 @@ Then you just add a line to every git commit message: Use your real name (sorry, no pseudonyms or anonymous contributions.) If you set your `user.name` and `user.email` git configs, you can sign your -commit automatically with `git commit -s`. +commit automatically with `git commit -s`. \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..78c3ec7 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,8 @@ +The MIT License (MIT) +Copyright © 2025 Intel Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..ac49ca0 --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +> [!IMPORTANT] +> This project is under development. All source code and features on the main branch are for the purpose of testing or evaluation and not production ready. + +# MFD Kernel Namespace + +Module to handle kernel namespaces. + +## API NETWORK NAMESPACE + +* add_namespace_call_command - method for extending command about namespace command call. + +## Usage + +```Python +from mfd_kernel_namespace import add_namespace_call_command + + +# Class example +class CustomPing: + def __init__(self, connection): + self._conn = connection + + def ping(self, namespace): + command = add_namespace_call_command("ping 1.0.0.0", namespace) + self._conn.start_process(command=command) + # or + self._conn.start_process(command=add_namespace_call_command("ping 1.0.0.0", namespace)) +``` + +## OS supported: + +* LINUX +* ESXI +* FREEBSD + +## Issue reporting + +If you encounter any bugs or have suggestions for improvements, you're welcome to contribute directly or open an issue [here](https://github.com/intel/mfd-kernel-namespace/issues). \ No newline at end of file diff --git a/examples/simple_example.py b/examples/simple_example.py new file mode 100644 index 0000000..a592bce --- /dev/null +++ b/examples/simple_example.py @@ -0,0 +1,19 @@ +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: MIT + +# Put here only the dependencies required to run the module. +# Development and test requirements should go to the corresponding files. +"""Simple example of usage.""" +from mfd_kernel_namespace import add_namespace_call_command + + +# Class example +class CustomPing: + def __init__(self, connection): + self._conn = connection + + def ping(self, namespace): + command = add_namespace_call_command("ping 1.0.0.1", namespace) + self._conn.start_process(command=command) + # or + self._conn.start_process(command=add_namespace_call_command("ping 1.0.0.1", namespace)) diff --git a/mfd_kernel_namespace/__init__.py b/mfd_kernel_namespace/__init__.py new file mode 100644 index 0000000..20b18e7 --- /dev/null +++ b/mfd_kernel_namespace/__init__.py @@ -0,0 +1,5 @@ +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: MIT +"""Module for MFD Kernel Namespace.""" + +from .network_namespace import add_namespace_call_command diff --git a/mfd_kernel_namespace/exceptions.py b/mfd_kernel_namespace/exceptions.py new file mode 100644 index 0000000..f287b3e --- /dev/null +++ b/mfd_kernel_namespace/exceptions.py @@ -0,0 +1,3 @@ +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: MIT +"""Module for custom exceptions.""" diff --git a/mfd_kernel_namespace/network_namespace.py b/mfd_kernel_namespace/network_namespace.py new file mode 100644 index 0000000..dc65587 --- /dev/null +++ b/mfd_kernel_namespace/network_namespace.py @@ -0,0 +1,22 @@ +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: MIT +"""Main module.""" + +import logging +from typing import Optional + +logger = logging.getLogger(__name__) + + +def add_namespace_call_command(command: str, namespace: Optional[str]) -> str: + """ + Add namespace call command to passed command if required. + + :param command: Command to extend + :param namespace: Namespace name + :return: Extended command + """ + if namespace is not None: + command = f"sh -c '{command}'" if "echo" in command else command + command = f"ip netns exec {namespace} {command}" + return command diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..c3960e9 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,27 @@ +[build-system] +requires = [ + "setuptools>=80.4.0", + "wheel" +] +build-backend = "setuptools.build_meta" + +[tool.setuptools.dynamic] +dependencies = { file = ["requirements.txt"] } + +[project] +name = "mfd-kernel-namespace" +description = "Module to handle kernel namespaces." +requires-python = ">=3.10, <3.14" +version = "1.7.0" +dynamic = ["dependencies"] +license-files = ["LICENSE.md", "AUTHORS.md"] +readme = {file = "README.md", content-type = "text/markdown"} + +[project.urls] +Homepage = "https://github.com/intel/mfd" +Repository = "https://github.com/intel/mfd-kernel-namespace" +Issues = "https://github.com/intel/mfd-kernel-namespace/issues" +Changelog = "https://github.com/intel/mfd-kernel-namespace/blob/main/CHANGELOG.md" + +[tool.setuptools.packages.find] +exclude = ["examples", "tests*", "sphinx-doc"] \ No newline at end of file diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..35ce018 --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,5 @@ +-r requirements-test.txt # Ensure tests dependencies are automatically included + +# Put additional dependencies needed for development here + +mfd-code-quality >= 1.2.0, < 2 \ No newline at end of file diff --git a/requirements-docs.txt b/requirements-docs.txt new file mode 100644 index 0000000..3012976 --- /dev/null +++ b/requirements-docs.txt @@ -0,0 +1,3 @@ +-r requirements.txt +sphinx +sphinx_rtd_theme_github_versions \ No newline at end of file diff --git a/requirements-test.txt b/requirements-test.txt new file mode 100644 index 0000000..f561012 --- /dev/null +++ b/requirements-test.txt @@ -0,0 +1,7 @@ +-r requirements.txt # Ensure tests dependencies are automatically included + +# Put dependencies required for testing the module here +pytest ~= 8.4 +pytest-mock ~= 3.14 + +coverage ~= 7.3.0 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..139597f --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ + + diff --git a/sphinx-doc/Makefile b/sphinx-doc/Makefile new file mode 100644 index 0000000..32df174 --- /dev/null +++ b/sphinx-doc/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SPHINXPROJ = MFD-Kernel-namespace +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/sphinx-doc/README.md b/sphinx-doc/README.md new file mode 100644 index 0000000..3641936 --- /dev/null +++ b/sphinx-doc/README.md @@ -0,0 +1,13 @@ +# MFD-KERNEL-NAMESPACE SPHINX DOCUMENTATION + +## HOW TO GENERATE DOCS +### 1. Download or use system embedded Python in version at least 3.7 +### 2. Create venv +- Create Python venv from MFD-Kernel-namespace requirements for Sphinx (`/requirements-docs.txt`) +- Link how to do this: `https://python.land/virtual-environments/virtualenv` +### 3. In Activated venv go to MFD-Kernel-namespace directory `/sphinx-doc` +### 4. Run command: +```shell +$ python generate_docs.py +``` +### 5. Open `/sphinx-doc/build/html/index.html` in Web browser to read documentation \ No newline at end of file diff --git a/sphinx-doc/conf.py b/sphinx-doc/conf.py new file mode 100644 index 0000000..19c5739 --- /dev/null +++ b/sphinx-doc/conf.py @@ -0,0 +1,165 @@ +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: MIT + +# MFD-Kernel-namespace documentation build configuration file, created by +# sphinx-quickstart on Fri Nov 24 14:52:29 2017. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +"""Configure file for sphinx docs.""" + +import os +import sys + +sys.path.append(os.path.abspath("..")) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + "sphinx.ext.autodoc", + "sphinx.ext.doctest", + "sphinx.ext.viewcode", + "sphinx.ext.autosummary", + "sphinx.ext.inheritance_diagram", +] + +autodoc_default_flags = ["members", "undoc-members", "private-members", "inherited-members", "show-inheritance"] +# Add any paths that contain templates here, relative to this directory. +templates_path = ["_templates"] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = ".rst" + +# The master toctree document. +master_doc = "index" + +# General information about the project. +project = "MFD-Kernel-namespace" +project_copyright = """Copyright (C) 2025 Intel Corporation +SPDX-License-Identifier: MIT""" +copyright = project_copyright # noqa +author = "Intel Corporation" + +# The full version, including alpha/beta/rc tags. +release = "" + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = "en" + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This patterns also effect to html_static_path and html_extra_path +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = "sphinx" + +todo_include_todos = False + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = "sphinx_rtd_theme_github_versions" + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +html_theme_options = { + "logo_only": False, + "display_version": True, + "prev_next_buttons_location": "bottom", + "style_external_links": False, + "vcs_pageview_mode": "", + # Toc options + "collapse_navigation": True, + "sticky_navigation": True, + "navigation_depth": 4, + "includehidden": True, + "titles_only": False, +} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ["_static"] + +# -- Options for HTMLHelp output ------------------------------------------ + +# Output file base name for HTML help builder. +htmlhelp_basename = "mfd-kernel-namespace-doc" + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, "mfd-kernel-namespace.tex", "MFD-Kernel-namespace Documentation", "author", "manual"), +] + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [(master_doc, "mfd-kernel-namespace", "MFD-Kernel-namespace Documentation", [author], 1)] + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ( + master_doc, + "MFD-Kernel-namespace", + "MFD-Kernel-namespace Documentation", + author, + "MFD-Kernel-namespace", + "One line description of project.", + "Miscellaneous", + ), +] diff --git a/sphinx-doc/generate_docs.py b/sphinx-doc/generate_docs.py new file mode 100644 index 0000000..0ac8858 --- /dev/null +++ b/sphinx-doc/generate_docs.py @@ -0,0 +1,18 @@ +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: MIT +"""Generate sphinx docs.""" + +import os +import shutil +import logging + +from sphinx.ext import apidoc +from sphinx.cmd import build + + +apidoc.main(["-e", "-o", "mfd_kernel_namespace", os.path.join("..", "mfd_kernel_namespace")]) + +build.main(["-b", "html", ".", "build/html"]) + +logging.info("Cleaning folders from build process...") +shutil.rmtree("mfd_kernel_namespace") diff --git a/sphinx-doc/genindex.rst b/sphinx-doc/genindex.rst new file mode 100644 index 0000000..a50680d --- /dev/null +++ b/sphinx-doc/genindex.rst @@ -0,0 +1,4 @@ +.. This file is a placeholder and will be replaced + +Index +##### \ No newline at end of file diff --git a/sphinx-doc/index.rst b/sphinx-doc/index.rst new file mode 100644 index 0000000..161fe50 --- /dev/null +++ b/sphinx-doc/index.rst @@ -0,0 +1,21 @@ +Welcome to MFD-Kernel-namespace's documentation! +====================================== + +.. toctree:: + :caption: Home + + Documentation Home + + +.. toctree:: + :caption: Main Documentation + :maxdepth: 4 + + MFD-Kernel-namespace Documentation + + +.. toctree:: + :caption: Appendix + + Python Module Index + Index \ No newline at end of file diff --git a/sphinx-doc/py-modindex.rst b/sphinx-doc/py-modindex.rst new file mode 100644 index 0000000..4d1ecb4 --- /dev/null +++ b/sphinx-doc/py-modindex.rst @@ -0,0 +1,4 @@ +.. This file is a placeholder and will be replaced + +Python Module Index +##### \ No newline at end of file diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..8ef2fad --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1,2 @@ +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: MIT diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py new file mode 100644 index 0000000..8ef2fad --- /dev/null +++ b/tests/unit/__init__.py @@ -0,0 +1,2 @@ +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: MIT diff --git a/tests/unit/test_mfd_kernel_namespace/__init__.py b/tests/unit/test_mfd_kernel_namespace/__init__.py new file mode 100644 index 0000000..8ef2fad --- /dev/null +++ b/tests/unit/test_mfd_kernel_namespace/__init__.py @@ -0,0 +1,2 @@ +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: MIT diff --git a/tests/unit/test_mfd_kernel_namespace/test_mfd_kernel_namespace.py b/tests/unit/test_mfd_kernel_namespace/test_mfd_kernel_namespace.py new file mode 100644 index 0000000..2cf139b --- /dev/null +++ b/tests/unit/test_mfd_kernel_namespace/test_mfd_kernel_namespace.py @@ -0,0 +1,15 @@ +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: MIT +"""Tests for `mfd_kernel_namespace` package.""" + +from mfd_kernel_namespace.network_namespace import add_namespace_call_command + + +class TestMfdKernelNamespace: + def test_add_namespace_call_command(self): + assert add_namespace_call_command("ethtool -i", "NS1") == "ip netns exec NS1 ethtool -i" + assert add_namespace_call_command("ethtool -i", None) == "ethtool -i" + + def test_add_namespace_call_command_with_echo(self): + assert add_namespace_call_command("echo 1 > /proc/...", "NS1") == "ip netns exec NS1 sh -c 'echo 1 > /proc/...'" + assert add_namespace_call_command("echo 1 > /proc/...", None) == "echo 1 > /proc/..."