Permalink
Browse files

MAJOR stuff. fixed major bug preventing satellite from deploying. add…

…ed a --reset flag to clear away any existing satellite (mostly for debugging). added a --version flag. most interestingly, added a --satellite flag that lets you run the satellite manually, and documented the SATELLITE environment variable you can use to point skypipe to your own satellite. oh, also removed dotcloud package since it's released and can now be a dependency, and changed the pyzmq-static dependency to pyzmq since they've merged
  • Loading branch information...
1 parent e059e30 commit 389ee3598051be7ce6f27bebac57456441002238 @progrium committed Nov 7, 2012
@@ -1,9 +0,0 @@
-#
-# All packages extending the dotcloud namespace must distribute their own
-# dotcloud/__init__.py with this exact content.
-#
-# See http://www.python.org/dev/peps/pep-0382/
-#
-
-from pkgutil import extend_path
-__path__ = extend_path(__path__, __name__)
@@ -1,2 +0,0 @@
-from .client import RESTClient
-
@@ -1,73 +0,0 @@
-import json
-import requests
-from requests.auth import HTTPBasicAuth
-
-class BaseAuth(object):
- def args_hook(self, args):
- pass
-
- def pre_request_hook(self, request):
- pass
-
- def response_hook(self, response):
- pass
-
-
-class NullAuth(BaseAuth):
- pass
-
-
-class BasicAuth(BaseAuth):
- def __init__(self, username, password):
- self.username = username
- self.password = password
-
- def args_hook(self, args):
- args['auth'] = HTTPBasicAuth(self.username, self.password)
-
-
-class OAuth2Auth(BaseAuth):
- def __init__(self, access_token=None, refresh_token=None, scope=None,
- client_id=None, client_secret=None, token_url=None):
- self.access_token = access_token
- self.refresh_token = refresh_token
- self.scope = scope
- self.client_id = client_id
- self.client_secret = client_secret
- self.token_url = token_url
- self._retry_count = 0
-
- def pre_request_hook(self, request):
- request.headers.setdefault('Authorization',
- 'Bearer {0}'.format(self.access_token))
-
- def response_hook(self, response):
- if response.status_code == requests.codes.unauthorized:
- if self._retry_count >= 1:
- return
- self._retry_count += 1
- if self.refresh_credentials():
- response.request.send(anyway=True)
- return response.request.response # override response
-
- def refresh_credentials(self):
- data = {
- 'grant_type': 'refresh_token',
- 'refresh_token': self.refresh_token,
- 'client_id': self.client_id,
- 'client_secret': self.client_secret,
- 'scope': self.scope or ''
- }
- if hasattr(self, 'pre_refresh_callback'):
- self.pre_refresh_callback(data)
- res = requests.post(self.token_url, data=data)
- res.raise_for_status()
- if not res.ok:
- return False
- data = json.loads(res.text)
- if data.get('access_token'):
- self.access_token = data['access_token']
- self.refresh_token = data['refresh_token']
- if hasattr(self, 'post_refresh_callback'):
- return self.post_refresh_callback(data)
- return False
@@ -1,113 +0,0 @@
-import requests
-import json
-import sys
-import os
-
-from .auth import BasicAuth, OAuth2Auth, NullAuth
-from .response import *
-from .errors import RESTAPIError, AuthenticationNotConfigured
-
-
-class RESTClient(object):
- def __init__(self, endpoint='https://rest.dotcloud.com/v1',
- debug=False, user_agent=None, version_checker=None):
- self.endpoint = endpoint
- self.debug = debug
- self.authenticator = NullAuth()
- self._make_session()
- self._user_agent = user_agent
- self._version_checker = version_checker
-
- def make_prefix_client(self, prefix=''):
- subclient = RESTClient(
- endpoint='{endpoint}{prefix}'.format(
- endpoint=self.endpoint, prefix=prefix),
- debug=self.debug, user_agent=self._user_agent,
- version_checker=self._version_checker)
- subclient.session = self.session
- return subclient
-
- def _make_session(self):
- headers = {'Accept': 'application/json'}
- hooks = {
- 'args': lambda args: self.authenticator.args_hook(args),
- 'pre_request': self._pre_request_hook,
- 'response': self._response_hook
- }
- self.session = requests.session(headers=headers, hooks=hooks,
- verify=True)
-
- def _pre_request_hook(self, request):
- if self._user_agent:
- request.headers['User-Agent'] = self._user_agent
- r = self.authenticator.pre_request_hook(request)
- if self.debug:
- print >>sys.stderr, '### {method} {url} data={data}'.format(
- method = request.method,
- url = request.path_url,
- data = request.data
- )
- return r
-
- def _response_hook(self, response):
- r = self.authenticator.response_hook(response)
- if self.debug:
- print >>sys.stderr, '### {code} TraceID:{trace_id}'.format(
- code=response.status_code,
- trace_id=response.headers['X-DotCloud-TraceID'])
- return r
-
- def build_url(self, path):
- if path == '' or path.startswith('/'):
- return self.endpoint + path
- else:
- return path
-
- def get(self, path='', streaming=False):
- return self.make_response(self.session.get(self.build_url(path),
- prefetch=not streaming), streaming)
-
- def post(self, path='', payload={}):
- return self.make_response(
- self.session.post(self.build_url(path), data=json.dumps(payload),
- headers={'Content-Type': 'application/json'}))
-
- def put(self, path='', payload={}):
- return self.make_response(
- self.session.put(self.build_url(path), data=json.dumps(payload),
- headers={'Content-Type': 'application/json'}))
-
- def delete(self, path=''):
- return self.make_response(
- self.session.delete(self.build_url(path),
- headers={'Content-Length': '0'}))
-
- def patch(self, path='', payload={}):
- return self.make_response(
- self.session.patch(self.build_url(path), data=json.dumps(payload),
- headers={'Content-Type': 'application/json'}))
-
- def make_response(self, res, streaming=False):
- trace_id = res.headers.get('X-DotCloud-TraceID')
- if res.headers['Content-Type'] == 'application/json':
- pass
- elif res.status_code == requests.codes.no_content:
- return BaseResponse.create(res=res, trace_id=trace_id)
- else:
- raise RESTAPIError(code=requests.codes.server_error,
- desc='Server responded with unsupported ' \
- 'media type: {0} (status: {1})' \
- .format(res.headers['Content-Type'],
- res.status_code),
- trace_id=trace_id)
- if not res.ok:
- data = json.loads(res.text)
- raise RESTAPIError(code=res.status_code,
- desc=data['error']['description'], trace_id=trace_id)
-
- if self._version_checker:
- self._version_checker(res.headers.get('X-DOTCLOUD-CLI-VERSION-MIN'),
- res.headers.get('X-DOTCLOUD-CLI-VERSION-CUR'))
-
- return BaseResponse.create(res=res, trace_id=trace_id,
- streaming=streaming)
@@ -1,11 +0,0 @@
-class RESTAPIError(Exception):
- def __init__(self, code=None, desc=None, trace_id=None):
- self.code = code
- self.desc = desc
- self.trace_id = trace_id
-
- def __str__(self):
- return self.desc
-
-class AuthenticationNotConfigured(Exception):
- pass
@@ -1,98 +0,0 @@
-import json
-import httplib # only for exception
-
-def bytes_to_lines(stream):
- """Reads single bytes from stream, emits lines.
-
- This hack makes me sick, but requests makes this impossible
- to do reliably, otherwise."""
- line = ""
- for byte in stream:
- line += byte
- if line.endswith("\r\n"):
- yield line
- line = ""
-
-class BaseResponse(object):
- def __init__(self, obj=None):
- self.obj = obj
-
- @classmethod
- def create(cls, res=None, trace_id=None, streaming=False):
- resp = None
-
- if streaming:
- stream = bytes_to_lines(res.iter_content(chunk_size=1))
- first_line = next(stream)
- data = json.loads(first_line)
- else:
- if res.text:
- data = json.loads(res.text)
- else:
- data = None
- if streaming:
- resp = StreamingJsonObjectResponse(obj=data['object'], stream=stream)
- elif data and 'object' in data:
- resp = ItemResponse(obj=data['object'])
- elif data and 'objects' in data:
- resp = ListResponse(obj=data['objects'])
- else:
- resp = NoItemResponse(obj=None)
- resp.trace_id = trace_id
- resp.res = res
- resp.data = data
- return resp
-
- def find_link(self, rel):
- for link in self.data.get('links', []):
- if link.get('rel') == rel:
- return link
- return None
-
-class ListResponse(BaseResponse):
- @property
- def items(self):
- return self.obj
-
- @property
- def item(self):
- return self.obj[0]
-
-class ItemResponse(BaseResponse):
- @property
- def items(self):
- return [self.obj]
-
- @property
- def item(self):
- return self.obj
-
-class NoItemResponse(BaseResponse):
- @property
- def items(self):
- return None
-
- @property
- def item(self):
- return None
-
-class StreamingJsonObjectResponse(BaseResponse):
- def __init__(self, obj, stream):
- BaseResponse.__init__(self, obj)
- self._stream = stream
-
- @property
- def items(self):
- def stream():
- try:
- for line in self._stream:
- line = line.rstrip()
- if line: # ignore empty lines (keep-alive)
- yield json.loads(line)['object']
- except httplib.HTTPException:
- pass # simply ignore when the connection is dropped
- return stream()
-
- @property
- def item(self):
- return self.obj
No changes.
Oops, something went wrong. Retry.

0 comments on commit 389ee35

Please sign in to comment.