diff options
author | Jonas Gunz <himself@jonasgunz.de> | 2020-12-10 20:40:14 +0100 |
---|---|---|
committer | Jonas Gunz <himself@jonasgunz.de> | 2020-12-10 20:48:39 +0100 |
commit | c22aedfb52c291ab791c3dfe6209c69047157cac (patch) | |
tree | 02a0a745406fd44f1ee766255f718ab08afc3b54 | |
download | python-phpipam-c22aedfb52c291ab791c3dfe6209c69047157cac.tar.gz |
initial
-rw-r--r-- | .gitignore | 138 | ||||
-rw-r--r-- | LICENSE | 19 | ||||
-rw-r--r-- | README.md | 7 | ||||
-rwxr-xr-x | phpipam/__init__.py | 162 | ||||
-rwxr-xr-x | setup.py | 19 |
5 files changed, 345 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a81c8ee --- /dev/null +++ b/.gitignore @@ -0,0 +1,138 @@ +# 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/ +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 +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# 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/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .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/ + +# 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/ + +# Cython debug symbols +cython_debug/ @@ -0,0 +1,19 @@ +Copyright (c) 2020 Jonas Gunz + +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..f4555cc --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# phpipam + +An incomplete phpIPAM API implementation for python + +[API Doc](https://phpipam.net/api-documentation/) + +License: MIT diff --git a/phpipam/__init__.py b/phpipam/__init__.py new file mode 100755 index 0000000..08a2466 --- /dev/null +++ b/phpipam/__init__.py @@ -0,0 +1,162 @@ + +import requests +import json +import datetime +from dateutil.parser import parse as datetime_parse + +class apiConnectionException(Exception): + pass + +class apiQueryException(Exception): + pass + +class apiObjectNotFoundException(Exception): + pass + +class phpipam: + """ + phpIPAM API Implementation + ReadOnly because I don't need the writing bit + + https://phpipam.net/api-documentation/ + """ + + def __init__(self, api_url, app_id, api_user, api_password): + """ + Parameters + ---------- + api_url : str + URL of the phpIPAM instance. Example: https://phpipam.example.com/ + app_id : str + AppID set in phpIPAM API settings + api_user : str + username, leave blank to use static token-authentication + api_password : str + user password or static auth token + + Raises + ------ + apiConnectionException + if the connection/authentification fails + """ + + self.api_url = api_url.strip('/') + '/api/' + app_id + self.api_user = api_user + self.api_password = api_password + + # Check for static auth + if len(self.api_user) == 0: + self.api_token = self.api_password + self.api_token_expires = "" + else: + self._getApiToken() + + def _req( self, method, url, data = {} ): + if self._isTokenExpired(): + self._getApiToken() + + return requests.request(method, self.api_url + url, data=data, headers={'token':self.api_token}).json() + + def _getApiToken(self): + data = requests.post(self.api_url + "/user", auth=(self.api_user,self.api_password)).json() + if not data['success']: + raise apiConnectionException('Failed to authenticate: ' + str(data['code'])) + + self.api_token = data['data']['token'] + self.api_token_expires = data['data']['expires'] + + + def _isTokenExpired(self): + # static auth does not expire + if len(self.api_token_expires) == 0: + return False + + expiration = datetime_parse(self.api_token_expires) + + return expiration < datetime.datetime.now() + + # TODO remove + def _checkTokenExpired(self): + data = self._req('GET', '/user/') + return data['success'] + + def _checkReq ( self, method, url, data = {} ): + """Wrapper for _req for checking result and only returning data""" + + data = self._req( method, url, data ) + + if not 'success' in data or not data['success']: + raise apiQueryException("Query failed with code " + str(data['code'] + ": " + str(['message']))) + + return data['data'] + + # + def getSections(self): + """ + Get the complete list of dictionaries describing sections + Returns: list of dicts + """ + + return self._checkReq('GET', '/sections/') + + def getSectionById(self, section_id): + """ + Get a section by id + + Parameters + ---------- + section_id : str + + Returns: dict + """ + + return self._checkReq('GET', f'/sections/{section_id}') + + + def getSectionByName(self, name): + """ + Find a section by name + + Parameters + ---------- + name : str + name of the section to search for + + Returns: dict + + Raises + ------ + apiObjectNotFoundException + if no section matches name + """ + + data = self.getSections() + + for section in data: + if 'name' in section and section['name'] == name: + return section + + raise apiObjectNotFoundException(f"Section {name} was not found.") + + def getSubnets(self, section_id): + """ + Get the complete list of dictionaries describing subnets of a section + + Parameters + ---------- + section_id : str + """ + + return self._checkReq('GET', f'/sections/{section_id}/subnets') + + def getSubnetById(self, subnet_id): + """ + Get a section by id + + Parameters + ---------- + subnet_id : str + """ + + return self._checkReq('GET', f'/subnets/{subnet_id}') + diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..35e50dd --- /dev/null +++ b/setup.py @@ -0,0 +1,19 @@ +from distutils.core import setup +import setuptools + +setup( + name='phpipam', + version='0.0.0-dev', + author="Jonas Gunz", + description="phpIPAM API implementation", + packages=setuptools.find_packages(), + license='MIT license', + long_description=open('README.md').read(), + long_description_content_type="text/markdown", + classifiers=[ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT", + "Operating System :: OS Independent", + ], +) + |