mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 17:09:03 +00:00
PEP-8 and PEP-257: ''' to """
This commit is contained in:
parent
d2094f8b60
commit
c192809517
@ -1,8 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=C0103,W0622
|
||||
'''
|
||||
"""
|
||||
Sphinx documentation for salt-api
|
||||
'''
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
@ -10,14 +10,14 @@ from sphinx.directives import TocTree
|
||||
|
||||
# pylint: disable=R0903
|
||||
class Mock(object):
|
||||
'''
|
||||
"""
|
||||
Mock out specified imports
|
||||
|
||||
This allows autodoc to do it's thing without having oodles of req'd
|
||||
installed libs. This doesn't work with ``import *`` imports.
|
||||
|
||||
http://read-the-docs.readthedocs.org/en/latest/faq.html#i-get-import-errors-on-libraries-that-depend-on-c-modules
|
||||
'''
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
'''
|
||||
"""
|
||||
Make api awesomeness
|
||||
'''
|
||||
"""
|
||||
# Import Python libs
|
||||
import inspect
|
||||
|
||||
@ -13,19 +13,19 @@ import salt.utils
|
||||
from salt.exceptions import SaltException, EauthAuthenticationError
|
||||
|
||||
class APIClient(object):
|
||||
'''
|
||||
"""
|
||||
Provide a uniform method of accessing the various client interfaces in Salt
|
||||
in the form of low-data data structures. For example:
|
||||
|
||||
>>> client = APIClient(__opts__)
|
||||
>>> lowstate = {'client': 'local', 'tgt': '*', 'fun': 'test.ping', 'arg': ''}
|
||||
>>> client.run(lowstate)
|
||||
'''
|
||||
"""
|
||||
def __init__(self, opts):
|
||||
self.opts = opts
|
||||
|
||||
def run(self, low):
|
||||
'''
|
||||
"""
|
||||
Execute the specified function in the specified client by passing the
|
||||
lowstate
|
||||
|
||||
@ -35,7 +35,7 @@ class APIClient(object):
|
||||
If 'wheel' or 'runner' prefixes fun then use associated salt client given
|
||||
by prefix in the specified 'sync' or 'async' mode.
|
||||
Otherwise use local salt client in the given 'sync' or 'async' mode
|
||||
'''
|
||||
"""
|
||||
|
||||
if not 'client' in low:
|
||||
low['client'] = 'async'
|
||||
@ -63,24 +63,24 @@ class APIClient(object):
|
||||
return ret
|
||||
|
||||
def local_async(self, *args, **kwargs):
|
||||
'''
|
||||
"""
|
||||
Wrap LocalClient for running :ref:`execution modules <all-salt.modules>`
|
||||
and immediately return the job ID. The results of the job can then be
|
||||
retrieved at a later time.
|
||||
|
||||
.. seealso:: :ref:`python-api`
|
||||
'''
|
||||
"""
|
||||
local = salt.client.LocalClient(self.opts['conf_file'])
|
||||
return local.run_job(*args, **kwargs)
|
||||
|
||||
async = local_async # default async client
|
||||
|
||||
def local_sync(self, *args, **kwargs):
|
||||
'''
|
||||
"""
|
||||
Wrap LocalClient for running :ref:`execution modules <all-salt.modules>`
|
||||
|
||||
.. seealso:: :ref:`python-api`
|
||||
'''
|
||||
"""
|
||||
local = salt.client.LocalClient(self.opts['conf_file'])
|
||||
return local.cmd(*args, **kwargs)
|
||||
|
||||
@ -88,9 +88,9 @@ class APIClient(object):
|
||||
sync = local_sync # default sync client
|
||||
|
||||
def runner_sync(self, fun, **kwargs):
|
||||
'''
|
||||
"""
|
||||
Wrap RunnerClient for executing :ref:`runner modules <all-salt.runners>`
|
||||
'''
|
||||
"""
|
||||
runner = salt.runner.RunnerClient(self.opts)
|
||||
return runner.low(fun, kwargs)
|
||||
|
||||
@ -98,9 +98,9 @@ class APIClient(object):
|
||||
runner_async = runner_sync # until we get an runner_async
|
||||
|
||||
def wheel_sync(self, fun, **kwargs):
|
||||
'''
|
||||
"""
|
||||
Wrap Wheel to enable executing :ref:`wheel modules <all-salt.wheel>`
|
||||
'''
|
||||
"""
|
||||
kwargs['fun'] = fun
|
||||
wheel = salt.wheel.Wheel(self.opts)
|
||||
return wheel.master_call(**kwargs)
|
||||
|
@ -1,6 +1,6 @@
|
||||
'''
|
||||
"""
|
||||
CLI entry-point for salt-api
|
||||
'''
|
||||
"""
|
||||
# Import python libs
|
||||
import sys
|
||||
import logging
|
||||
@ -26,9 +26,9 @@ log = logging.getLogger(__name__)
|
||||
|
||||
class SaltAPI(OptionParser, ConfigDirMixIn, LogLevelMixIn, PidfileMixin,
|
||||
DaemonMixIn, MergeConfigMixIn):
|
||||
'''
|
||||
"""
|
||||
The cli parser object used to fire up the salt api system.
|
||||
'''
|
||||
"""
|
||||
__metaclass__ = OptionParserMeta
|
||||
|
||||
VERSION = saltapi.version.__version__
|
||||
@ -42,9 +42,9 @@ class SaltAPI(OptionParser, ConfigDirMixIn, LogLevelMixIn, PidfileMixin,
|
||||
return saltapi.config.api_config(self.get_config_file_path())
|
||||
|
||||
def run(self):
|
||||
'''
|
||||
"""
|
||||
Run the api
|
||||
'''
|
||||
"""
|
||||
self.parse_args()
|
||||
try:
|
||||
if self.config['verify_env']:
|
||||
|
@ -1,6 +1,6 @@
|
||||
'''
|
||||
"""
|
||||
The main entry point for salt-api
|
||||
'''
|
||||
"""
|
||||
# Import python libs
|
||||
import logging
|
||||
import multiprocessing
|
||||
@ -11,15 +11,15 @@ import saltapi.loader
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class SaltAPIClient(object):
|
||||
'''
|
||||
'''
|
||||
"""
|
||||
"""
|
||||
def __init__(self, opts):
|
||||
self.opts = opts
|
||||
|
||||
def run(self):
|
||||
'''
|
||||
"""
|
||||
Load and start all available api modules
|
||||
'''
|
||||
"""
|
||||
netapi = saltapi.loader.netapi(self.opts)
|
||||
for fun in netapi:
|
||||
if fun.endswith('.start'):
|
||||
|
@ -1,6 +1,6 @@
|
||||
'''
|
||||
"""
|
||||
Manage configuration files in salt-api
|
||||
'''
|
||||
"""
|
||||
|
||||
# Import salt libs
|
||||
import salt.config
|
||||
@ -14,10 +14,10 @@ DEFAULT_API_OPTS = {
|
||||
|
||||
|
||||
def api_config(path):
|
||||
'''
|
||||
"""
|
||||
Read in the salt master config file and add additional configs that
|
||||
need to be stubbed out for salt-api
|
||||
'''
|
||||
"""
|
||||
# Let's grab a copy of salt's master default opts
|
||||
defaults = salt.config.DEFAULT_MASTER_OPTS
|
||||
# Let's override them with salt-api's required defaults
|
||||
|
@ -1,6 +1,6 @@
|
||||
'''
|
||||
"""
|
||||
The salt api module loader interface
|
||||
'''
|
||||
"""
|
||||
# Import python libs
|
||||
import os
|
||||
|
||||
@ -10,9 +10,9 @@ import saltapi
|
||||
|
||||
|
||||
def netapi(opts):
|
||||
'''
|
||||
"""
|
||||
Return the network api functions
|
||||
'''
|
||||
"""
|
||||
load = salt.loader._create_loader(
|
||||
opts,
|
||||
'netapi',
|
||||
@ -22,10 +22,10 @@ def netapi(opts):
|
||||
return load.gen_functions()
|
||||
|
||||
def runner(opts):
|
||||
'''
|
||||
"""
|
||||
Load the runners, this function bypasses the issue with the altered
|
||||
basepath
|
||||
'''
|
||||
"""
|
||||
load = salt.loader._create_loader(
|
||||
opts,
|
||||
'runners',
|
||||
|
@ -1,8 +1,8 @@
|
||||
'''
|
||||
"""
|
||||
A script to start the CherryPy WSGI server
|
||||
|
||||
This is run by ``salt-api`` and started in a multiprocess.
|
||||
'''
|
||||
"""
|
||||
# pylint: disable=C0103
|
||||
|
||||
# Import Python libs
|
||||
@ -58,9 +58,9 @@ def __virtual__():
|
||||
return False
|
||||
|
||||
def verify_certs(self, *args):
|
||||
'''
|
||||
"""
|
||||
Sanity checking for the specified SSL certificates
|
||||
'''
|
||||
"""
|
||||
msg = ("Could not find a certificate: {0}\n"
|
||||
"If you want to quickly generate a self-signed certificate, "
|
||||
"use the tls.create_self_signed_cert function in Salt")
|
||||
@ -70,9 +70,9 @@ def verify_certs(self, *args):
|
||||
raise Exception(msg.format(arg))
|
||||
|
||||
def start():
|
||||
'''
|
||||
"""
|
||||
Start the server loop
|
||||
'''
|
||||
"""
|
||||
from . import app
|
||||
root, apiopts, conf = app.get_app(__opts__)
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
'''
|
||||
"""
|
||||
A REST API for Salt
|
||||
===================
|
||||
|
||||
@ -153,7 +153,7 @@ functionality is available at that URL. The other URLs are largely convenience
|
||||
URLs that wrap that main entry point with shorthand or specialized
|
||||
functionality.
|
||||
|
||||
'''
|
||||
"""
|
||||
# We need a custom pylintrc here...
|
||||
# pylint: disable=W0212,E1101,C0103,R0201,W0221,W0613
|
||||
|
||||
@ -179,10 +179,10 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def salt_token_tool():
|
||||
'''
|
||||
"""
|
||||
If the custom authentication header is supplied, put it in the cookie dict
|
||||
so the rest of the session-based auth works as intended
|
||||
'''
|
||||
"""
|
||||
x_auth = cherrypy.request.headers.get('X-Auth-Token', None)
|
||||
|
||||
# X-Auth-Token header trumps session cookie
|
||||
@ -191,10 +191,10 @@ def salt_token_tool():
|
||||
|
||||
|
||||
def salt_ip_verify_tool():
|
||||
'''
|
||||
"""
|
||||
If there is a list of restricted IPs, verify current
|
||||
client is coming from one of those IPs.
|
||||
'''
|
||||
"""
|
||||
# This is overly cumbersome and crude,
|
||||
# But, it's also safe... ish...
|
||||
salt_config = cherrypy.config.get('saltopts', None)
|
||||
@ -218,9 +218,9 @@ def salt_ip_verify_tool():
|
||||
|
||||
|
||||
def salt_auth_tool():
|
||||
'''
|
||||
"""
|
||||
Redirect all unauthenticated requests to the login page
|
||||
'''
|
||||
"""
|
||||
# Redirect to the login page if the session hasn't been authed
|
||||
if not cherrypy.session.has_key('token'):
|
||||
raise cherrypy.InternalRedirect('/login')
|
||||
@ -239,14 +239,14 @@ ct_out_map = (
|
||||
)
|
||||
|
||||
def hypermedia_handler(*args, **kwargs):
|
||||
'''
|
||||
"""
|
||||
Determine the best output format based on the Accept header, execute the
|
||||
regular handler, and transform the output to the request content type (even
|
||||
if it's an error).
|
||||
|
||||
:param args: Pass args through to the main handler
|
||||
:param kwargs: Pass kwargs through to the main handler
|
||||
'''
|
||||
"""
|
||||
# Execute the real handler. Handle or pass-through any errors we know how
|
||||
# to handle (auth & HTTP errors). Reformat any errors we don't know how to
|
||||
# handle as a data structure.
|
||||
@ -282,12 +282,12 @@ def hypermedia_handler(*args, **kwargs):
|
||||
|
||||
|
||||
def hypermedia_out():
|
||||
'''
|
||||
"""
|
||||
Determine the best handler for the requested content type
|
||||
|
||||
Wrap the normal handler and transform the output from that handler into the
|
||||
requested content type
|
||||
'''
|
||||
"""
|
||||
request = cherrypy.serving.request
|
||||
request._hypermedia_inner_handler = request.handler
|
||||
request.handler = hypermedia_handler
|
||||
@ -297,9 +297,9 @@ def hypermedia_out():
|
||||
|
||||
@functools.wraps
|
||||
def process_request_body(fn):
|
||||
'''
|
||||
"""
|
||||
A decorator to skip a processor function if process_request_body is False
|
||||
'''
|
||||
"""
|
||||
def wrapped(*args, **kwargs):
|
||||
if cherrypy.request.process_request_body != False:
|
||||
fn(*args, **kwargs)
|
||||
@ -307,7 +307,7 @@ def process_request_body(fn):
|
||||
|
||||
|
||||
def urlencoded_processor(entity):
|
||||
'''
|
||||
"""
|
||||
Accept x-www-form-urlencoded data (run through CherryPy's formatter)
|
||||
and reformat it into a Low State data structure.
|
||||
|
||||
@ -321,7 +321,7 @@ def urlencoded_processor(entity):
|
||||
-d fun='test.kwarg' -d arg='one=1' -d arg='two=2'
|
||||
|
||||
:param entity: raw POST data
|
||||
'''
|
||||
"""
|
||||
# First call out to CherryPy's default processor
|
||||
cherrypy._cpreqbody.process_urlencoded(entity)
|
||||
lowdata = entity.params
|
||||
@ -336,11 +336,11 @@ def urlencoded_processor(entity):
|
||||
|
||||
@process_request_body
|
||||
def json_processor(entity):
|
||||
'''
|
||||
"""
|
||||
Unserialize raw POST data in JSON format to a Python data structure.
|
||||
|
||||
:param entity: raw POST data
|
||||
'''
|
||||
"""
|
||||
body = entity.fp.read()
|
||||
try:
|
||||
cherrypy.serving.request.lowstate = json.loads(body)
|
||||
@ -350,11 +350,11 @@ def json_processor(entity):
|
||||
|
||||
@process_request_body
|
||||
def yaml_processor(entity):
|
||||
'''
|
||||
"""
|
||||
Unserialize raw POST data in YAML format to a Python data structure.
|
||||
|
||||
:param entity: raw POST data
|
||||
'''
|
||||
"""
|
||||
body = entity.fp.read()
|
||||
try:
|
||||
cherrypy.serving.request.lowstate = yaml.load(body)
|
||||
@ -363,7 +363,7 @@ def yaml_processor(entity):
|
||||
|
||||
|
||||
def hypermedia_in():
|
||||
'''
|
||||
"""
|
||||
Unserialize POST/PUT data of a specified Content-Type.
|
||||
|
||||
The following custom processors all are intended to format Low State data
|
||||
@ -371,7 +371,7 @@ def hypermedia_in():
|
||||
|
||||
:raises HTTPError: if the request contains a Content-Type that we do not
|
||||
have a processor for
|
||||
'''
|
||||
"""
|
||||
# Be liberal in what you accept
|
||||
ct_in_map = {
|
||||
'application/x-www-form-urlencoded': urlencoded_processor,
|
||||
@ -393,11 +393,11 @@ def hypermedia_in():
|
||||
|
||||
|
||||
class LowDataAdapter(object):
|
||||
'''
|
||||
"""
|
||||
The primary entry point to the REST API. All functionality is available
|
||||
through this URL. The other available URLs provide convenience wrappers
|
||||
around this URL.
|
||||
'''
|
||||
"""
|
||||
exposed = True
|
||||
|
||||
_cp_config = {
|
||||
@ -419,11 +419,11 @@ class LowDataAdapter(object):
|
||||
self.api = saltapi.APIClient(self.opts)
|
||||
|
||||
def exec_lowstate(self):
|
||||
'''
|
||||
"""
|
||||
Pull a Low State data structure from request and execute the low-data
|
||||
chunks through Salt. The low-data chunks will be updated to include the
|
||||
authorization token for the current session.
|
||||
'''
|
||||
"""
|
||||
lowstate = cherrypy.request.lowstate
|
||||
token = cherrypy.session.get('token', None)
|
||||
|
||||
@ -433,7 +433,7 @@ class LowDataAdapter(object):
|
||||
yield self.api.run(chunk)
|
||||
|
||||
def GET(self):
|
||||
'''
|
||||
"""
|
||||
.. http:get:: /
|
||||
|
||||
An explanation of the API with links of where to go next.
|
||||
@ -458,7 +458,7 @@ class LowDataAdapter(object):
|
||||
:status 200: success
|
||||
:status 401: authentication required
|
||||
:status 406: requested Content-Type not available
|
||||
'''
|
||||
"""
|
||||
import inspect
|
||||
|
||||
# Grab all available client interfaces
|
||||
@ -476,7 +476,7 @@ class LowDataAdapter(object):
|
||||
}
|
||||
|
||||
def POST(self, **kwargs):
|
||||
'''
|
||||
"""
|
||||
The primary execution interface for the rest of the API
|
||||
|
||||
.. http:post:: /
|
||||
@ -527,7 +527,7 @@ class LowDataAdapter(object):
|
||||
:status 200: success
|
||||
:status 401: authentication required
|
||||
:status 406: requested Content-Type not available
|
||||
'''
|
||||
"""
|
||||
return {
|
||||
'return': list(self.exec_lowstate()),
|
||||
}
|
||||
@ -535,7 +535,7 @@ class LowDataAdapter(object):
|
||||
|
||||
class Minions(LowDataAdapter):
|
||||
def GET(self, mid=None):
|
||||
'''
|
||||
"""
|
||||
A convenience URL for getting lists of minions or getting minion
|
||||
details
|
||||
|
||||
@ -571,7 +571,7 @@ class Minions(LowDataAdapter):
|
||||
:status 200: success
|
||||
:status 401: authentication required
|
||||
:status 406: requested Content-Type not available
|
||||
'''
|
||||
"""
|
||||
cherrypy.request.lowstate = [{
|
||||
'client': 'local', 'tgt': mid or '*', 'fun': 'grains.items',
|
||||
}]
|
||||
@ -580,7 +580,7 @@ class Minions(LowDataAdapter):
|
||||
}
|
||||
|
||||
def POST(self, **kwargs):
|
||||
'''
|
||||
"""
|
||||
Start an execution command and immediately return the job id
|
||||
|
||||
.. http:post:: /minions
|
||||
@ -634,7 +634,7 @@ class Minions(LowDataAdapter):
|
||||
:status 202: success
|
||||
:status 401: authentication required
|
||||
:status 406: requested :mailheader:`Content-Type` not available
|
||||
'''
|
||||
"""
|
||||
for chunk in cherrypy.request.lowstate:
|
||||
chunk['client'] = 'local_async'
|
||||
job_data = list(self.exec_lowstate())
|
||||
@ -651,7 +651,7 @@ class Minions(LowDataAdapter):
|
||||
|
||||
class Jobs(LowDataAdapter):
|
||||
def GET(self, jid=None):
|
||||
'''
|
||||
"""
|
||||
A convenience URL for getting lists of previously run jobs or getting
|
||||
the return from a single job
|
||||
|
||||
@ -717,7 +717,7 @@ class Jobs(LowDataAdapter):
|
||||
:status 200: success
|
||||
:status 401: authentication required
|
||||
:status 406: requested Content-Type not available
|
||||
'''
|
||||
"""
|
||||
cherrypy.request.lowstate = [{
|
||||
'client': 'runner',
|
||||
'fun': 'jobs.lookup_jid' if jid else 'jobs.list_jobs',
|
||||
@ -729,7 +729,7 @@ class Jobs(LowDataAdapter):
|
||||
|
||||
|
||||
class Login(LowDataAdapter):
|
||||
'''
|
||||
"""
|
||||
All interactions with this REST API must be authenticated. Authentication
|
||||
is performed through Salt's eauth system. You must set the eauth backend
|
||||
and allowed users by editing the :conf_master:`external_auth` section in
|
||||
@ -743,7 +743,7 @@ class Login(LowDataAdapter):
|
||||
|
||||
If the request is initiated programmatically, the request must contain a
|
||||
:mailheader:`X-Auth-Token` header with valid and active session id.
|
||||
'''
|
||||
"""
|
||||
_cp_config = dict(LowDataAdapter._cp_config, **{
|
||||
'tools.salt_token.on': False,
|
||||
'tools.salt_auth.on': False,
|
||||
@ -756,7 +756,7 @@ class Login(LowDataAdapter):
|
||||
self.auth = salt.auth.LoadAuth(self.opts)
|
||||
|
||||
def GET(self):
|
||||
'''
|
||||
"""
|
||||
Present the login interface
|
||||
|
||||
.. http:get:: /login
|
||||
@ -782,7 +782,7 @@ class Login(LowDataAdapter):
|
||||
|
||||
:status 401: authentication required
|
||||
:status 406: requested Content-Type not available
|
||||
'''
|
||||
"""
|
||||
cherrypy.response.status = '401 Unauthorized'
|
||||
cherrypy.response.headers['WWW-Authenticate'] = 'Session'
|
||||
|
||||
@ -792,7 +792,7 @@ class Login(LowDataAdapter):
|
||||
}
|
||||
|
||||
def POST(self, **kwargs):
|
||||
'''
|
||||
"""
|
||||
Authenticate against Salt's eauth system
|
||||
|
||||
.. versionchanged:: 0.8.0
|
||||
@ -851,7 +851,7 @@ class Login(LowDataAdapter):
|
||||
:status 200: success
|
||||
:status 401: could not authenticate using provided credentials
|
||||
:status 406: requested Content-Type not available
|
||||
'''
|
||||
"""
|
||||
# the urlencoded_processor will wrap this in a list
|
||||
if isinstance(cherrypy.serving.request.lowstate, list):
|
||||
creds = cherrypy.serving.request.lowstate[0]
|
||||
@ -890,11 +890,11 @@ class Logout(LowDataAdapter):
|
||||
})
|
||||
|
||||
def POST(self):
|
||||
'''
|
||||
"""
|
||||
Destroy the currently active session and expire the session cookie
|
||||
|
||||
.. versionadded:: 0.8.0
|
||||
'''
|
||||
"""
|
||||
cherrypy.lib.sessions.expire() # set client-side to expire
|
||||
cherrypy.session.regenerate() # replace server-side with new
|
||||
|
||||
@ -909,16 +909,16 @@ class Run(LowDataAdapter):
|
||||
})
|
||||
|
||||
def exec_lowstate(self):
|
||||
'''
|
||||
"""
|
||||
Override exec_lowstate to avoid pulling token from the session
|
||||
'''
|
||||
"""
|
||||
lowstate = cherrypy.request.lowstate
|
||||
|
||||
for chunk in lowstate:
|
||||
yield self.api.run(chunk)
|
||||
|
||||
def POST(self, **kwargs):
|
||||
'''
|
||||
"""
|
||||
Run commands bypassing the normal session handling
|
||||
|
||||
.. versionadded:: 0.8.0
|
||||
@ -971,19 +971,19 @@ class Run(LowDataAdapter):
|
||||
:status 200: success
|
||||
:status 401: authentication failed
|
||||
:status 406: requested Content-Type not available
|
||||
'''
|
||||
"""
|
||||
return {
|
||||
'return': list(self.exec_lowstate()),
|
||||
}
|
||||
|
||||
|
||||
class Events(object):
|
||||
'''
|
||||
"""
|
||||
The event bus on the Salt master exposes a large variety of things, notably
|
||||
when executions are started on the master and also when minions ultimately
|
||||
return their results. This URL provides a real-time window into a running
|
||||
Salt infrastructure.
|
||||
'''
|
||||
"""
|
||||
exposed = True
|
||||
|
||||
_cp_config = dict(LowDataAdapter._cp_config, **{
|
||||
@ -1002,7 +1002,7 @@ class Events(object):
|
||||
self.auth = salt.auth.LoadAuth(self.opts)
|
||||
|
||||
def GET(self, token=None):
|
||||
'''
|
||||
"""
|
||||
Return an HTTP stream of the Salt master event bus; this stream is
|
||||
formatted per the Server Sent Events (SSE) spec
|
||||
|
||||
@ -1044,7 +1044,7 @@ class Events(object):
|
||||
|
||||
:status 200: success
|
||||
:status 401: could not authenticate using provided credentials
|
||||
'''
|
||||
"""
|
||||
# Pulling the session token from an URL param is a workaround for
|
||||
# browsers not supporting CORS in the EventSource API.
|
||||
if token:
|
||||
@ -1084,9 +1084,9 @@ class App(object):
|
||||
|
||||
|
||||
class API(object):
|
||||
'''
|
||||
"""
|
||||
Collect configuration and URL map for building the CherryPy app
|
||||
'''
|
||||
"""
|
||||
url_map = {
|
||||
'index': LowDataAdapter,
|
||||
'login': Login,
|
||||
@ -1108,10 +1108,10 @@ class API(object):
|
||||
setattr(self, self.apiopts.get('app_path', 'app').lstrip('/'), App())
|
||||
|
||||
def get_conf(self):
|
||||
'''
|
||||
"""
|
||||
Combine the CherryPy configuration with the rest_cherrypy config values
|
||||
pulled from the master config and return the CherryPy configuration
|
||||
'''
|
||||
"""
|
||||
conf = {
|
||||
'global': {
|
||||
'server.socket_host': self.apiopts.get('host', '0.0.0.0'),
|
||||
@ -1143,9 +1143,9 @@ class API(object):
|
||||
|
||||
|
||||
def get_app(opts):
|
||||
'''
|
||||
"""
|
||||
Returns a WSGI app and a configuration dictionary
|
||||
'''
|
||||
"""
|
||||
apiopts = opts.get(__name__.rsplit('.', 2)[-2], {}) # rest_cherrypy opts
|
||||
|
||||
# Add Salt and salt-api config options to the main CherryPy config dict
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
'''
|
||||
"""
|
||||
Deployment
|
||||
==========
|
||||
|
||||
@ -36,7 +36,7 @@ An example Apache virtual host configuration::
|
||||
WSGIScriptAlias / /path/to/saltapi/netapi/rest_cherrypy/wsgi.py
|
||||
</VirtualHost>
|
||||
|
||||
'''
|
||||
"""
|
||||
# pylint: disable=C0103
|
||||
|
||||
import os
|
||||
@ -44,9 +44,9 @@ import os
|
||||
import cherrypy
|
||||
|
||||
def bootstrap_app():
|
||||
'''
|
||||
"""
|
||||
Grab the opts dict of the master config by trying to import Salt
|
||||
'''
|
||||
"""
|
||||
from . import app
|
||||
import salt.config
|
||||
|
||||
@ -56,11 +56,11 @@ def bootstrap_app():
|
||||
|
||||
|
||||
def get_application(*args):
|
||||
'''
|
||||
"""
|
||||
Returns a WSGI application function. If you supply the WSGI app and config
|
||||
it will use that, otherwise it will try to obtain them from a local Salt
|
||||
installation
|
||||
'''
|
||||
"""
|
||||
opts_tuple = args
|
||||
|
||||
def wsgi_app(environ, start_response):
|
||||
|
@ -1,4 +1,4 @@
|
||||
'''
|
||||
"""
|
||||
A minimalist REST API for Salt
|
||||
==============================
|
||||
|
||||
@ -128,7 +128,7 @@ Usage examples
|
||||
:status 200: success
|
||||
:status 401: authentication required
|
||||
|
||||
'''
|
||||
"""
|
||||
import errno
|
||||
import json
|
||||
import os
|
||||
@ -158,18 +158,18 @@ def __virtual__():
|
||||
return False
|
||||
|
||||
class HTTPError(Exception):
|
||||
'''
|
||||
"""
|
||||
A custom exception that can take action based on an HTTP error code
|
||||
'''
|
||||
"""
|
||||
def __init__(self, code, message):
|
||||
self.code = code
|
||||
Exception.__init__(self, '{0}: {1}'.format(code, message))
|
||||
|
||||
def mkdir_p(path):
|
||||
'''
|
||||
"""
|
||||
mkdir -p
|
||||
http://stackoverflow.com/a/600612/127816
|
||||
'''
|
||||
"""
|
||||
try:
|
||||
os.makedirs(path)
|
||||
except OSError as exc: # Python >2.5
|
||||
@ -178,18 +178,18 @@ def mkdir_p(path):
|
||||
else: raise
|
||||
|
||||
def read_body(environ):
|
||||
'''
|
||||
"""
|
||||
Pull the body from the request and return it
|
||||
'''
|
||||
"""
|
||||
length = environ.get('CONTENT_LENGTH', '0')
|
||||
length = 0 if length == '' else int(length)
|
||||
|
||||
return environ['wsgi.input'].read(length)
|
||||
|
||||
def get_json(environ):
|
||||
'''
|
||||
"""
|
||||
Return the request body as JSON
|
||||
'''
|
||||
"""
|
||||
content_type = environ.get('CONTENT_TYPE', '')
|
||||
if content_type != 'application/json':
|
||||
raise HTTPError(406, 'JSON required')
|
||||
@ -200,10 +200,10 @@ def get_json(environ):
|
||||
raise HTTPError(400, exc)
|
||||
|
||||
def get_headers(data, extra_headers=None):
|
||||
'''
|
||||
"""
|
||||
Takes the response data as well as any additional headers and returns a
|
||||
tuple of tuples of headers suitable for passing to start_response()
|
||||
'''
|
||||
"""
|
||||
response_headers = {
|
||||
'Content-Length': str(len(data)),
|
||||
}
|
||||
@ -214,20 +214,20 @@ def get_headers(data, extra_headers=None):
|
||||
return response_headers.items()
|
||||
|
||||
def run_chunk(environ, lowstate):
|
||||
'''
|
||||
"""
|
||||
Expects a list of lowstate dictionaries that are executed and returned in
|
||||
order
|
||||
'''
|
||||
"""
|
||||
client = environ['SALT_APIClient']
|
||||
|
||||
for chunk in lowstate:
|
||||
yield client.run(chunk)
|
||||
|
||||
def dispatch(environ):
|
||||
'''
|
||||
"""
|
||||
Do any path/method dispatching here and return a JSON-serializable data
|
||||
structure appropriate for the response
|
||||
'''
|
||||
"""
|
||||
method = environ['REQUEST_METHOD'].upper()
|
||||
|
||||
if method == 'GET':
|
||||
@ -240,9 +240,9 @@ def dispatch(environ):
|
||||
raise HTTPError(405, 'Method Not Allowed')
|
||||
|
||||
def saltenviron(environ):
|
||||
'''
|
||||
"""
|
||||
Make Salt's opts dict and the APIClient available in the WSGI environ
|
||||
'''
|
||||
"""
|
||||
if not '__opts__' in locals():
|
||||
import salt.config
|
||||
__opts__ = salt.config.client_config(
|
||||
@ -252,10 +252,10 @@ def saltenviron(environ):
|
||||
environ['SALT_APIClient'] = saltapi.APIClient(__opts__)
|
||||
|
||||
def application(environ, start_response):
|
||||
'''
|
||||
"""
|
||||
Process the request and return a JSON response. Catch errors and return the
|
||||
appropriate HTTP code.
|
||||
'''
|
||||
"""
|
||||
# Instantiate APIClient once for the whole app
|
||||
saltenviron(environ)
|
||||
|
||||
@ -287,9 +287,9 @@ def application(environ, start_response):
|
||||
return (ret,)
|
||||
|
||||
def start():
|
||||
'''
|
||||
"""
|
||||
Start simple_server()
|
||||
'''
|
||||
"""
|
||||
from wsgiref.simple_server import make_server
|
||||
|
||||
short_name = __name__.rsplit('.')[-1]
|
||||
|
Loading…
Reference in New Issue
Block a user