Squashed 'modules/libjuju/' changes from c50c361..c127833
c127833 Bump version and changelog for release
6aff679 k8s bundles no longer have application placement (#293)
1de9ad1 Add retry for connection if all endpoints fail (#288)
8cb8d75 Support generation of registration string for model sharing. (#279)
a9e2fd6 Add Twine for dist upload on release (#284)
407a6a6 Update and prepare for 0.11.2 release (#282)
d102620 call related update credential cloud facade methods based on facade version (#281)
2acbdc4 Add test case for redirect during connect (#275)
35fb43e Implement App.get_resources and pinned resources in bundles (#278)
b5ba51a Bump version and changelog for release
7a73a0a Fix bundles with subordinates for Juju <2.5 (#277)
a0f950f Bump version and changelog for release
01125e2 Updates for new Juju version (#274)
87d9388 Fix wrong variable name in revoke_model function (#271)
2b43065 Bump version and changelog for release
98ee524 set include_stats to false to reduce request time (#266)
61e1d69 Update version and changelog for 0.10.1
82f9968 Retry ssh in manual provision test (#265)
d64bfff Clean up lint and add lint coverage to travis config (#263)
c7c5c54 Increase the timeout for charmstore connections (#262)
4a6e398 Fix log level of `Driver connected to juju` message (#258)
514e479 Update version and changelog for 0.10.0
ec2c493 Reorder scp parameters (#259) (#260)
26c86c8 Implement set/get model constraints (#253)
c6b4ab4 Update version and changelog for 0.9.1
e863746 Update websockets to 6.0 (#254)
567bc1a Update version and changelog for 0.9.0
b275ced python3.7 compatibility updates (#251)
bc7336a Handle juju not installed in is_bootstrapped. (#250)
1ce8e0b Add app.reset_config(list). (#249)
c620d4f Implement model.get_action_status (#248)
96ea3c4 Fix `make client` in Python 3.6 (#247)
61969ea Update version and changelog for release
ebf6882 Add support for adding a manual (ssh) machine (#240)
18422f4 Backwards compatibility fixes (#213)
40c0211 Implement model.get_action_output (#242)
c6b8ac5 Fix JSON serialization error for bundle with lxd to unit placement (#243)
5014fc3 Fix reference in docs to connect_current (#239)
ebe0193 Wrap machine agent status workaround in version check (#238)
462989b Convert seconds to nanoseconds for juju.unit.run (#237)
0f413e6 Fix spurious intermittent failure in test_machines.py::test_status (#236)
ce36b60 Define an unused juju-zfs lxd storage pool (#235)
dfc2e8d Add support for Application get_actions (#234)
e7e8c13 Update version and changelog for release
499337b Surface errors from bundle plan (#233)
2d94186 Always send auth-tag even with macaroon auth (#217)
000355c Inline jsonfile credential when sending to controller (#231)
9805123 Bump VERSION and changelog for release
27d723b Always parse tags and spaces constraints to lists (#228)
668945a Doc index improvements (#211)
65e6b5e Add doc req to force newer pymacaroons to fix RTD builds
e2abd47 Fix dependency conflict for building docs
2907a6e Bump VERSION and changelog for 0.7.3 release
37a7500 Full macaroon bakery support (#206)
a06e313 Fix regression with deploying local charm, add test case (#209)
75e9a2b Expose a machines series (#208)
46c98f5 Revert non-functional switch to Py3.6, just specify Py3 instead (#205)
8a99ad1 Cherry-pick VERSION and changelog bump from 0.7.2 release branch
88121d6 Support deploying bundle YAML file directly (rather than just directory) (#202)
57c0dbf Cherry-pick #197 into master (#198)
0973edc Update VERSION and changelog for 0.7.0
f5a4108 Add deprecated placeholder for Controller.get_models
17dffa4 JujuData abstract base class (#194)
76f22cc Make Model and Controller connect methods backwardly compatible (#196)
19b5658 Fix race condition in adding relations (#192)
978f35c refactor connections prior to bakery authentication (#187)
77c0f04 sort all imports; lint tests (#188)
4740935 juju.client.gocookies: new module (#186)
2c4de22 all: use pyrfc3339 instead of dateutil (#185)
7133ffe juju/client: factor out JujuData class (#182)
476b832 Fix race condition in connection monitor test (#183)
e64a5d1 Fix example in README (#178)
97355cc Fix rare hang during Unit.run (#177)
ae0b091 #176: Fix licensing quirks
c0d001b Refactor model handling (#171)
ab807c8 Refactor users handling, add get_users (#170)
5270db5 Upload credential to controller when adding model (#168)
16d8390 Support 'applications' key in bundles (#165)
2de3eed Improve handling of thread error handling for loop.run() (#169)
7807023 Fix encoding when using to_json() (#166)
73effb1 Fix intermittent test failures (#167)
46da148 Update VERSION and changelog for release
3dda1dc Fix test failures (#163)
14392af removing cli command to add ssh keys (#161)
ce68170 Make Application.upgrade_charm upgrade resources (#158)
git-subtree-dir: modules/libjuju
git-subtree-split: c12783304945fdff5c28397b82b535a9cc065ca3
diff --git a/examples/action.py b/examples/action.py
index 0f25647..f839f11 100644
--- a/examples/action.py
+++ b/examples/action.py
@@ -7,7 +7,6 @@
4. Waits for the action results to come back, then exits.
"""
-import asyncio
import logging
from juju import loop
@@ -27,8 +26,8 @@
async def main():
model = Model()
- await model.connect_current()
- await model.reset(force=True)
+ # connect to current model with current user, per Juju CLI
+ await model.connect()
app = await model.deploy(
'git',
diff --git a/examples/add_machine.py b/examples/add_machine.py
index 8ae2d40..33d0c34 100755
--- a/examples/add_machine.py
+++ b/examples/add_machine.py
@@ -19,7 +19,7 @@
async def main():
model = Model()
- await model.connect_current()
+ await model.connect()
try:
# add a new default machine
diff --git a/examples/add_model.py b/examples/add_model.py
index 3e46490..88766f1 100644
--- a/examples/add_model.py
+++ b/examples/add_model.py
@@ -19,7 +19,8 @@
async def main():
controller = Controller()
print("Connecting to controller")
- await controller.connect_current()
+ # connect to current controller with current user, per Juju CLI
+ await controller.connect()
try:
model_name = "addmodeltest-{}".format(uuid.uuid4())
diff --git a/examples/allwatcher.py b/examples/allwatcher.py
index c78d689..884230b 100644
--- a/examples/allwatcher.py
+++ b/examples/allwatcher.py
@@ -16,7 +16,7 @@
async def watch():
- conn = await Connection.connect_current()
+ conn = await Connection.connect()
allwatcher = client.AllWatcherFacade.from_connection(conn)
while True:
change = await allwatcher.Next()
diff --git a/examples/config.py b/examples/config.py
index bacc840..c7580f6 100644
--- a/examples/config.py
+++ b/examples/config.py
@@ -6,7 +6,6 @@
3. Deploys a charm and prints its config and constraints
"""
-import asyncio
import logging
from juju.model import Model
@@ -19,8 +18,8 @@
async def main():
model = Model()
- await model.connect_current()
- await model.reset(force=True)
+ # connect to current model with current user, per Juju CLI
+ await model.connect()
ubuntu_app = await model.deploy(
'mysql',
@@ -47,7 +46,7 @@
await model.disconnect()
-
+
if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG)
ws_logger = logging.getLogger('websockets.protocol')
diff --git a/examples/connect_current_model.py b/examples/connect_current_model.py
new file mode 100644
index 0000000..b46a09c
--- /dev/null
+++ b/examples/connect_current_model.py
@@ -0,0 +1,27 @@
+"""
+This is a very basic example that connects to the currently selected model
+and prints the number of applications deployed to it.
+"""
+import logging
+
+from juju import loop
+from juju.model import Model
+
+log = logging.getLogger(__name__)
+
+
+async def main():
+ model = Model()
+ try:
+ # connect to the current model with the current user, per the Juju CLI
+ await model.connect()
+ print('There are {} applications'.format(len(model.applications)))
+ finally:
+ if model.is_connected():
+ print('Disconnecting from model')
+ await model.disconnect()
+
+
+if __name__ == '__main__':
+ logging.basicConfig(level=logging.INFO)
+ loop.run(main())
diff --git a/examples/controller.py b/examples/controller.py
index 6002f68..b61a6f6 100644
--- a/examples/controller.py
+++ b/examples/controller.py
@@ -8,7 +8,6 @@
5. Destroys the model
"""
-import asyncio
import logging
from juju.controller import Controller
@@ -17,7 +16,8 @@
async def main():
controller = Controller()
- await controller.connect_current()
+ # connect to current controller with current user, per Juju CLI
+ await controller.connect()
model = await controller.add_model(
'my-test-model',
'aws',
diff --git a/examples/credential.py b/examples/credential.py
new file mode 100644
index 0000000..e653536
--- /dev/null
+++ b/examples/credential.py
@@ -0,0 +1,47 @@
+import sys
+from juju import loop
+from juju.controller import Controller
+
+
+async def main(cloud_name, credential_name):
+ controller = Controller()
+ model = None
+ print('Connecting to controller')
+ # connect to current controller with current user, per Juju CLI
+ await controller.connect()
+ try:
+ print('Adding model')
+ model = await controller.add_model(
+ 'test',
+ cloud_name=cloud_name,
+ credential_name=credential_name)
+
+ # verify credential
+ print("Verify model's credential: {}".format(
+ model.info.cloud_credential_tag))
+
+ # verify we can deploy
+ print('Deploying ubuntu')
+ app = await model.deploy('ubuntu-10')
+
+ print('Waiting for active')
+ await model.block_until(
+ lambda: app.units and all(unit.workload_status == 'active'
+ for unit in app.units))
+
+ print('Removing ubuntu')
+ await app.remove()
+ finally:
+ print('Cleaning up')
+ if model:
+ print('Removing model')
+ model_uuid = model.info.uuid
+ await model.disconnect()
+ await controller.destroy_model(model_uuid)
+ print('Disconnecting')
+ await controller.disconnect()
+
+
+if __name__ == '__main__':
+ assert len(sys.argv) > 2, 'Please provide a cloud and credential name'
+ loop.run(main(sys.argv[1], sys.argv[2]))
diff --git a/examples/deploy.py b/examples/deploy.py
index e6c306a..43764d7 100644
--- a/examples/deploy.py
+++ b/examples/deploy.py
@@ -13,7 +13,8 @@
async def main():
model = Model()
print('Connecting to model')
- await model.connect_current()
+ # connect to current model with current user, per Juju CLI
+ await model.connect()
try:
print('Deploying ubuntu')
diff --git a/examples/fullstatus.py b/examples/fullstatus.py
index cdaf51d..5548423 100644
--- a/examples/fullstatus.py
+++ b/examples/fullstatus.py
@@ -5,7 +5,7 @@
from juju import loop
async def status():
- conn = await Connection.connect_current()
+ conn = await Connection.connect()
client = ClientFacade.from_connection(conn)
patterns = None
diff --git a/examples/future.py b/examples/future.py
index 0180325..5e974cf 100644
--- a/examples/future.py
+++ b/examples/future.py
@@ -2,7 +2,6 @@
This example doesn't work - it demonstrates features that don't exist yet.
"""
-import asyncio
import logging
from juju.model import Model
@@ -11,8 +10,8 @@
async def main():
model = Model()
- await model.connect_current()
- await model.reset(force=True)
+ # connect to current model with current user, per Juju CLI
+ await model.connect()
goal_state = Model.from_yaml('bundle-like-thing')
ubuntu_app = await model.deploy(
diff --git a/examples/leadership.py b/examples/leadership.py
index b231003..dbd1b6e 100644
--- a/examples/leadership.py
+++ b/examples/leadership.py
@@ -13,7 +13,7 @@
async def report_leadership():
model = Model()
- await model.connect_current()
+ await model.connect()
print("Leadership: ")
for app in model.applications.values():
diff --git a/examples/livemodel.py b/examples/livemodel.py
index 47eb999..1b10ac9 100644
--- a/examples/livemodel.py
+++ b/examples/livemodel.py
@@ -6,8 +6,6 @@
3. Runs forever (kill with Ctrl-C)
"""
-import asyncio
-
from juju.model import Model
from juju import loop
@@ -21,7 +19,8 @@
async def watch_model():
model = Model()
- await model.connect_current()
+ # connect to current model with current user, per Juju CLI
+ await model.connect()
model.add_observer(on_model_change)
diff --git a/examples/localcharm.py b/examples/localcharm.py
index 978703e..b9481d4 100644
--- a/examples/localcharm.py
+++ b/examples/localcharm.py
@@ -15,7 +15,7 @@
async def main():
model = Model()
- await model.connect_current()
+ await model.connect()
# Deploy a local charm using a path to the charm directory
await model.deploy(
diff --git a/examples/relate.py b/examples/relate.py
index 8f1e708..347e021 100644
--- a/examples/relate.py
+++ b/examples/relate.py
@@ -40,59 +40,63 @@
async def main():
model = Model()
- await model.connect_current()
+ # connect to current model with current user, per Juju CLI
+ await model.connect()
- model.add_observer(MyRemoveObserver())
- await model.reset(force=True)
- model.add_observer(MyModelObserver())
+ try:
+ model.add_observer(MyRemoveObserver())
+ await model.reset(force=True)
+ model.add_observer(MyModelObserver())
- ubuntu_app = await model.deploy(
- 'ubuntu',
- application_name='ubuntu',
- series='trusty',
- channel='stable',
- )
- ubuntu_app.on_change(asyncio.coroutine(
- lambda delta, old_app, new_app, model:
- print('App changed: {}'.format(new_app.entity_id))
- ))
- ubuntu_app.on_remove(asyncio.coroutine(
- lambda delta, old_app, new_app, model:
- print('App removed: {}'.format(old_app.entity_id))
- ))
- ubuntu_app.on_unit_add(asyncio.coroutine(
- lambda delta, old_unit, new_unit, model:
- print('Unit added: {}'.format(new_unit.entity_id))
- ))
- ubuntu_app.on_unit_remove(asyncio.coroutine(
- lambda delta, old_unit, new_unit, model:
- print('Unit removed: {}'.format(old_unit.entity_id))
- ))
- unit_a, unit_b = await ubuntu_app.add_units(count=2)
- unit_a.on_change(asyncio.coroutine(
- lambda delta, old_unit, new_unit, model:
- print('Unit changed: {}'.format(new_unit.entity_id))
- ))
- await model.deploy(
- 'nrpe',
- application_name='nrpe',
- series='trusty',
- channel='stable',
- # subordinates must be deployed without units
- num_units=0,
- )
- my_relation = await model.add_relation(
- 'ubuntu',
- 'nrpe',
- )
- my_relation.on_remove(asyncio.coroutine(
- lambda delta, old_rel, new_rel, model:
- print('Relation removed: {}'.format(old_rel.endpoints))
- ))
+ ubuntu_app = await model.deploy(
+ 'ubuntu',
+ application_name='ubuntu',
+ series='trusty',
+ channel='stable',
+ )
+ ubuntu_app.on_change(asyncio.coroutine(
+ lambda delta, old_app, new_app, model:
+ print('App changed: {}'.format(new_app.entity_id))
+ ))
+ ubuntu_app.on_remove(asyncio.coroutine(
+ lambda delta, old_app, new_app, model:
+ print('App removed: {}'.format(old_app.entity_id))
+ ))
+ ubuntu_app.on_unit_add(asyncio.coroutine(
+ lambda delta, old_unit, new_unit, model:
+ print('Unit added: {}'.format(new_unit.entity_id))
+ ))
+ ubuntu_app.on_unit_remove(asyncio.coroutine(
+ lambda delta, old_unit, new_unit, model:
+ print('Unit removed: {}'.format(old_unit.entity_id))
+ ))
+ unit_a, unit_b = await ubuntu_app.add_units(count=2)
+ unit_a.on_change(asyncio.coroutine(
+ lambda delta, old_unit, new_unit, model:
+ print('Unit changed: {}'.format(new_unit.entity_id))
+ ))
+ await model.deploy(
+ 'nrpe',
+ application_name='nrpe',
+ series='trusty',
+ channel='stable',
+ # subordinates must be deployed without units
+ num_units=0,
+ )
+ my_relation = await model.add_relation(
+ 'ubuntu',
+ 'nrpe',
+ )
+ my_relation.on_remove(asyncio.coroutine(
+ lambda delta, old_rel, new_rel, model:
+ print('Relation removed: {}'.format(old_rel.endpoints))
+ ))
+ finally:
+ await model.disconnect()
if __name__ == '__main__':
- logging.basicConfig(level=logging.DEBUG)
+ logging.basicConfig(level=logging.INFO)
ws_logger = logging.getLogger('websockets.protocol')
ws_logger.setLevel(logging.INFO)
loop.run(main())
diff --git a/examples/unitrun.py b/examples/unitrun.py
index 3dfacd6..805f0ae 100644
--- a/examples/unitrun.py
+++ b/examples/unitrun.py
@@ -7,7 +7,6 @@
4. Waits for the action results to come back, then exits.
"""
-import asyncio
import logging
from juju.model import Model
@@ -24,8 +23,8 @@
async def main():
model = Model()
- await model.connect_current()
- await model.reset(force=True)
+ # connect to current model with current user, per Juju CLI
+ await model.connect()
app = await model.deploy(
'ubuntu-0',