/usr/lib/python2.7/dist-packages/quickstart/juju.py is in juju-quickstart 1.3.1-0ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | # This file is part of the Juju Quickstart Plugin, which lets users set up a
# Juju environment in very few steps (https://launchpad.net/juju-quickstart).
# Copyright (C) 2013 Canonical Ltd.
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License version 3, as published by
# the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
# SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Juju Quickstart API client."""
from __future__ import unicode_literals
import logging
import jujuclient
import websocket
def connect(api_url):
"""Return an Environment instance connected to the given API URL."""
connection = WebSocketConnection()
# See the websocket.create_connection function.
connection.settimeout(websocket.default_timeout)
connection.connect(api_url, origin=api_url)
return Environment(api_url, conn=connection)
class Environment(jujuclient.Environment):
"""A Juju bootstrapped environment.
Instances of this class can be used to run API operations on a Juju
environment. Specifically this subclass enables bundle support and
deployments to specific machines.
"""
def deploy_bundle(self, yaml, name=None, bundle_id=None):
"""Deploy a bundle."""
params = {'YAML': yaml}
if name is not None:
params['Name'] = name
if bundle_id is not None:
params['BundleID'] = bundle_id
request = {
'Type': 'Deployer',
'Request': 'Import',
'Params': params,
}
return self._rpc(request)
def create_auth_token(self):
"""Make an auth token creation request.
Here is an example of a successful token creation response.
{
'RequestId': 42,
'Response': {
'Token': 'TOKEN-STRING',
'Created': '2013-11-21T12:34:46.778866Z',
'Expires': '2013-11-21T12:36:46.778866Z'
}
}
"""
request = dict(Type='GUIToken', Request='Create')
return self._rpc(request)
def get_watcher(self):
"""Return a connected/authenticated environment watcher.
This method is similar to jujuclient.Environment.get_watch, but it
enables logging on the resulting watcher requests/responses traffic.
"""
# Logging is enabled by the connect factory function, which uses our
# customized WebSocketConnection. Note that, since jujuclient does not
# track request identifiers, it is not currently possible to avoid
# establishing a new connection for each watcher.
env = connect(self.endpoint)
# For the remaining bits, see jujuclient.Environment.get_watch.
env.login(**self._creds)
watcher = jujuclient.Watcher(env.conn)
self._watches.append(watcher)
watcher.start()
return watcher
def get_status(self):
"""Return the current status of the environment.
The status is represented by a single mega-watcher changeset.
Each change in the changeset is a tuple (entity, action, data) where:
- entity is a string representing the changed content type
(e.g. "service" or "unit");
- action is a string representing the event which generated the
change (i.e. "change" or "remove");
- data is a dict containing information about the releated entity.
"""
with self.get_watcher() as watcher:
changeset = watcher.next()
return changeset
def watch_changes(self, processor):
"""Start watching the changes occurring in the Juju environment.
For each changeset, call the given processor callable, and yield
the values returned by the processor.
"""
with self.get_watcher() as watcher:
# The watcher closes when the context manager exit hook is called.
for changeset in watcher:
changes = processor(changeset)
if changes:
yield changes
class WebSocketConnection(websocket.WebSocket):
"""A WebSocket client connection."""
def send(self, message):
"""Send the given WebSocket message.
Overridden to add logging.
"""
logging.debug('API message: --> {}'.format(message.decode('utf-8')))
return super(WebSocketConnection, self).send(message)
def recv(self):
"""Receive a message from the WebSocket server.
Overridden to add logging.
"""
message = super(WebSocketConnection, self).recv()
logging.debug('API message: <-- {}'.format(message.decode('utf-8')))
return message
|