-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4451 from ryanpetrello/awxkit
open source awxkit Reviewed-by: https://github.com/softwarefactory-project-zuul[bot]
- Loading branch information
Showing
104 changed files
with
10,487 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
# Byte-compiled / optimized / DLL files | ||
__pycache__/ | ||
*.py[cod] | ||
*$py.class | ||
|
||
# C extensions | ||
*.so | ||
|
||
# Distribution / packaging | ||
.Python | ||
env/ | ||
build/ | ||
develop-eggs/ | ||
dist/ | ||
downloads/ | ||
eggs/ | ||
.eggs/ | ||
lib/ | ||
lib64/ | ||
parts/ | ||
sdist/ | ||
var/ | ||
*.egg-info/ | ||
.installed.cfg | ||
*.egg | ||
|
||
# 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/ | ||
.coverage | ||
.coverage.* | ||
.cache | ||
nosetests.xml | ||
coverage.xml | ||
report.xml | ||
report.pylama | ||
*,cover | ||
.hypothesis/ | ||
|
||
# Translations | ||
*.mo | ||
*.pot | ||
|
||
# Django stuff: | ||
*.log | ||
local_settings.py | ||
|
||
# Flask stuff: | ||
instance/ | ||
.webassets-cache | ||
|
||
# Scrapy stuff: | ||
.scrapy | ||
|
||
# Sphinx documentation | ||
docs/_build/ | ||
|
||
# PyBuilder | ||
target/ | ||
|
||
# IPython Notebook | ||
.ipynb_checkpoints | ||
|
||
# pyenv | ||
.python-version | ||
|
||
# celery beat schedule file | ||
celerybeat-schedule | ||
|
||
# dotenv | ||
.env | ||
|
||
# virtualenv | ||
venv/ | ||
ENV/ | ||
|
||
# Spyder project settings | ||
.spyderproject | ||
|
||
# Rope project settings | ||
.ropeproject | ||
|
||
# vim | ||
*.swp | ||
|
||
# mac OS | ||
*.DS_Store | ||
|
||
# pytest | ||
*.pytest_cache |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
include requirements.txt | ||
include setup.py | ||
recursive-include awxkit *.py *.yml *.md | ||
recursive-include test *.py *.yml *.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
awxkit | ||
====== | ||
|
||
Python library that backs the provided `awx` command line client. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
from .api import pages, client, resources # NOQA | ||
from .config import config # NOQA | ||
from . import awx # NOQA | ||
from .ws import WSClient # NOQA |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from .pages import * # NOQA | ||
from .client import * # NOQA |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
import logging | ||
|
||
import requests | ||
|
||
from awxkit import exceptions as exc | ||
from awxkit.config import config | ||
|
||
|
||
log = logging.getLogger(__name__) | ||
|
||
|
||
class ConnectionException(exc.Common): | ||
|
||
pass | ||
|
||
|
||
class Token_Auth(requests.auth.AuthBase): | ||
def __init__(self, token, auth_type='Token'): | ||
self.token = token | ||
self.auth_type = auth_type | ||
|
||
def __call__(self, request): | ||
request.headers['Authorization'] = '{0.auth_type} {0.token}'.format(self) | ||
return request | ||
|
||
|
||
def log_elapsed(r, *args, **kwargs): # requests hook to display API elapsed time | ||
log.debug('"{0.request.method} {0.url}" elapsed: {0.elapsed}'.format(r)) | ||
|
||
|
||
class Connection(object): | ||
"""A requests.Session wrapper for establishing connection w/ AWX instance""" | ||
|
||
def __init__(self, server, verify=False): | ||
self.server = server | ||
self.verify = verify | ||
|
||
if not self.verify: | ||
requests.packages.urllib3.disable_warnings() | ||
|
||
self.session = requests.Session() | ||
self.uses_session_cookie = False | ||
|
||
def get_session_requirements(self, next='/api/'): | ||
self.get('/api/') # this causes a cookie w/ the CSRF token to be set | ||
return dict(next=next) | ||
|
||
def login(self, username=None, password=None, token=None, **kwargs): | ||
if username and password: | ||
_next = kwargs.get('next') | ||
if _next: | ||
headers = self.session.headers.copy() | ||
self.post('/api/login/', headers=headers, | ||
data=dict(username=username, password=password, next=_next)) | ||
self.session_id = self.session.cookies.get('sessionid') | ||
self.uses_session_cookie = True | ||
else: | ||
self.session.auth = (username, password) | ||
elif token: | ||
self.session.auth = Token_Auth(token, auth_type=kwargs.get('auth_type', 'Token')) | ||
else: | ||
self.session.auth = None | ||
|
||
def logout(self): | ||
if self.uses_session_cookie: | ||
self.session.cookies.pop('sessionid', None) | ||
else: | ||
self.session.auth = None | ||
|
||
def request(self, relative_endpoint, method='get', json=None, data=None, query_parameters=None, headers=None): | ||
"""Core requests.Session wrapper that returns requests.Response objects""" | ||
session_request_method = getattr(self.session, method, None) | ||
if not session_request_method: | ||
raise ConnectionException(message="Unknown request method: {0}".format(method)) | ||
|
||
use_endpoint = relative_endpoint | ||
if self.server.endswith('/') and use_endpoint.startswith('/'): | ||
raise RuntimeError('AWX URL given with trailing slash, remove slash.') | ||
url = '{0.server}{1}'.format(self, use_endpoint) | ||
|
||
kwargs = dict(verify=self.verify, params=query_parameters, json=json, data=data, | ||
hooks=dict(response=log_elapsed)) | ||
|
||
if headers is not None: | ||
kwargs['headers'] = headers | ||
|
||
if method in ('post', 'put', 'patch', 'delete'): | ||
kwargs.setdefault('headers', {})['X-CSRFToken'] = self.session.cookies.get('csrftoken') | ||
kwargs['headers']['Referer'] = url | ||
|
||
for attempt in range(1, config.client_connection_attempts + 1): | ||
try: | ||
response = session_request_method(url, **kwargs) | ||
break | ||
except requests.exceptions.ConnectionError as err: | ||
if attempt == config.client_connection_attempts: | ||
raise err | ||
log.exception('Failed to reach url: {0}. Retrying.'.format(url)) | ||
|
||
return response | ||
|
||
def delete(self, relative_endpoint): | ||
return self.request(relative_endpoint, method='delete') | ||
|
||
def get(self, relative_endpoint, query_parameters=None, headers=None): | ||
return self.request(relative_endpoint, method='get', query_parameters=query_parameters, headers=headers) | ||
|
||
def head(self, relative_endpoint): | ||
return self.request(relative_endpoint, method='head') | ||
|
||
def options(self, relative_endpoint): | ||
return self.request(relative_endpoint, method='options') | ||
|
||
def patch(self, relative_endpoint, json): | ||
return self.request(relative_endpoint, method='patch', json=json) | ||
|
||
def post(self, relative_endpoint, json=None, data=None, headers=None): | ||
return self.request(relative_endpoint, method='post', json=json, data=data, headers=headers) | ||
|
||
def put(self, relative_endpoint, json): | ||
return self.request(relative_endpoint, method='put', json=json) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
from .has_create import * # NOQA | ||
from .has_instance_groups import HasInstanceGroups # NOQA | ||
from .has_notifications import HasNotifications # NOQA | ||
from .has_status import HasStatus # NOQA | ||
from .has_survey import HasSurvey # NOQA | ||
from .has_variables import HasVariables # NOQA | ||
from .has_copy import HasCopy # NOQA |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
from awxkit.api.pages import Page | ||
from awxkit.utils import random_title | ||
|
||
|
||
class HasCopy(object): | ||
|
||
def can_copy(self): | ||
return self.get_related('copy').can_copy | ||
|
||
def copy(self, name=''): | ||
"""Return a copy of current page""" | ||
payload = {"name": name or "Copy - " + random_title()} | ||
endpoint = self.json.related['copy'] | ||
page = Page(self.connection, endpoint=endpoint) | ||
return page.post(payload) |
Oops, something went wrong.