Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
9c9ecbc
Update websockets library to work with Py3.9+
johnsca Jan 28, 2021
cc84118
Implement add_space and get_spaces
Jan 30, 2021
7c2294a
Add facade versions 4 & 5 to Spaces
Jan 31, 2021
2a20c2b
Fix blank line lint
Feb 1, 2021
d696937
Merge pull request #467 from gnuoy/issue/466
jujubot Feb 1, 2021
5b6b2d3
Merge branch 'master' into johnsca/update-websockets/py39
johnsca Feb 1, 2021
3ce73c2
Add support for .charm files
johnsca Feb 2, 2021
cb58030
Remove unnecessary version-specific testenv from tox.ini
johnsca Feb 3, 2021
4e4e108
Merge pull request #465 from juju/johnsca/update-websockets/py39
jujubot Feb 4, 2021
db54074
Merge branch 'master' into johnsca/accept-charm-files
johnsca Feb 4, 2021
3d91d6b
Merge pull request #469 from juju/johnsca/accept-charm-files
jujubot Feb 4, 2021
c6ddcac
Fix bundles referencing .charm files and add wait_for_bundle
johnsca Feb 4, 2021
707f045
Make Model.wait_for_idle more generic
johnsca Feb 5, 2021
fd36c8f
Merge pull request #470 from juju/johnsca/bundle-charm-files-and-wait
jujubot Feb 8, 2021
40c9866
Release 2.8.5 notes
SimonRichardson Feb 8, 2021
7829fd0
Merge pull request #471 from SimonRichardson/release-2.8.5
jujubot Feb 8, 2021
1015f4d
Expand wait_for_idle to support waiting for status (#473)
johnsca Feb 11, 2021
aaadff3
Introduce hostname property to Machine model
achilleasa Mar 12, 2021
fd1438c
Merge pull request #475 from achilleasa/provide-accessor-for-machine-…
jujubot Mar 12, 2021
dc80236
Fix the typo in the param name
SimonRichardson Mar 15, 2021
7f96863
Merge pull request #478 from SimonRichardson/scale-typo
jujubot Mar 15, 2021
a16e80e
Update to latest juju 2.8.10 schema
SimonRichardson Mar 15, 2021
3e23b74
Merge pull request #479 from SimonRichardson/schema-update-2.8.10
jujubot Mar 15, 2021
facd1f1
Release 2.8.6 notes
SimonRichardson Mar 23, 2021
5e23162
Merge pull request #480 from SimonRichardson/release-2.8.6
jujubot Mar 23, 2021
d6ea321
Merge branch 'master' of git://github.com/juju/python-libjuju into 2.9
SimonRichardson Mar 31, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 25 additions & 4 deletions .github/workflows/tox.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,36 @@ name: Unit Tests
on: [push, pull_request]

jobs:
lint:
name: Lint
runs-on: ubuntu-latest
strategy:
matrix:
python: [3.5, 3.6, 3.7, 3.8, 3.9]
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python }}
- name: Install dependencies
run: |
pip install tox
- name: Run lint
run: tox -e lint
unit-tests:
runs-on: ubuntu-latest
strategy:
matrix:
python: [3.5, 3.6, 3.7, 3.8, 3.9]
steps:
- uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v1
with:
python-version: 3.8
- name: Install Tox and any other packages
python-version: ${{ matrix.python }}
- name: Install dependencies
run: pip install tox
- name: Run Lint and Unit Tests
run: tox -e lint,py3
- name: Run unit tests
run: tox -e py3
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.8.4
2.8.6
21 changes: 21 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
Changelog
---------

2.8.6
^^^^^

Tuesday March 23 2021

* Update facade methods for Juju 2.8.10
* Bug fix - Fix typo in param name for ScaleApplications
* Introduction of hostname property for Machines

2.8.5
^^^^^

Monday February 8 2021

* Implement add_space and get_spaces.
* Update facade controllers.
* Support already archived (.charm or .zip) local charms.
* Introduction of wait_for_bundle method.
* Bug fix - Handle None in list_offers results
* Bug fix - Update libraries to support Python 3.9+

2.8.4
^^^^^

Expand Down
46 changes: 46 additions & 0 deletions examples/machine_hostname.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env python3.5

"""
This example:

1. Connects to the current model
2. Creates a machine
3. Waits for the machine agent to start and prints out the reported machine
hostname.

NOTE: this example requires a 2.8.10+ controller.
"""
import logging

from juju import loop
from juju.model import Model

MB = 1
GB = 1024


async def main():
model = Model()
await model.connect()

try:
# Add a machine and wait until the machine agents starts
machine1 = await model.add_machine()
await model.block_until(
lambda: machine1.agent_status == 'started')

# At this point we can access the reported hostname via the hostname
# property of the machine model.
print("machine1 hostname: {}".format(machine1.hostname))

await machine1.destroy(force=True)
finally:
await model.disconnect()


if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG)
ws_logger = logging.getLogger('websockets.protocol')
ws_logger.setLevel(logging.INFO)

loop.run(main())
6 changes: 3 additions & 3 deletions juju/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,9 @@ async def scale(self, scale=None, scale_change=None):
self.name, 'to' if scale else 'by', scale or scale_change)

await app_facade.ScaleApplications(applications=[
client.ScaleApplicationParam(application_tag=self.tag,
scale=scale,
scale_change=scale_change)
client.ScaleApplicationParams(application_tag=self.tag,
scale=scale,
scale_change=scale_change)
])

def allocate(self, budget, value):
Expand Down
37 changes: 28 additions & 9 deletions juju/bundle.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import asyncio
import logging
import os
import zipfile
from pathlib import Path

import yaml
Expand Down Expand Up @@ -72,7 +73,7 @@ async def _validate_bundle(self, bundle):
)
return bundle

async def _handle_local_charms(self, bundle):
async def _handle_local_charms(self, bundle, bundle_dir):
"""Search for references to local charms (i.e. filesystem paths)
in the bundle. Upload the local charms to the model, and replace
the filesystem paths with appropriate 'local:' paths in the bundle.
Expand All @@ -89,9 +90,16 @@ async def _handle_local_charms(self, bundle):
apps_dict = bundle.get('applications', bundle.get('services', {}))
for app_name in self.applications:
app_dict = apps_dict[app_name]
charm_dir = os.path.abspath(os.path.expanduser(app_dict['charm']))
if not os.path.isdir(charm_dir):
continue
charm_dir = app_dict['charm']
try:
charm_path = (bundle_dir / charm_dir).resolve()
if not (charm_path.is_dir() or
(charm_path.is_file() and
charm_path.suffix in ('.charm', '.zip'))):
continue
charm_dir = str(charm_path)
except ValueError:
pass
series = (
app_dict.get('series') or
default_series or
Expand Down Expand Up @@ -122,18 +130,24 @@ async def _handle_local_charms(self, bundle):

async def fetch_plan(self, entity_id):
is_store_url = entity_id.startswith('cs:')
is_local = False
bundle_dir = None

if not is_store_url and os.path.isfile(entity_id):
bundle_yaml = Path(entity_id).read_text()
is_local = True
bundle_dir = Path(entity_id).parent
elif not is_store_url and os.path.isdir(entity_id):
bundle_yaml = (Path(entity_id) / "bundle.yaml").read_text()
bundle_dir = Path(entity_id)
else:
bundle_yaml = await self.charmstore.files(entity_id,
filename='bundle.yaml',
read_file=True)
self.bundle = yaml.safe_load(bundle_yaml)
self.bundle = await self._validate_bundle(self.bundle)
self.bundle = await self._handle_local_charms(self.bundle)
if is_local:
self.bundle = await self._handle_local_charms(self.bundle, bundle_dir)

self.plan = await self.bundle_facade.GetChanges(
bundleurl=entity_id,
Expand Down Expand Up @@ -179,11 +193,16 @@ def get_charm_series(path):

Returns None if no series can be determined.
"""
md = Path(path) / "metadata.yaml"
if not md.exists():
return None
try:
data = yaml.safe_load(md.open())
if path.endswith('.charm'):
md = "metadata.yaml in %s" % path
with zipfile.ZipFile(path, 'r') as charm_file:
data = yaml.safe_load(charm_file.read('metadata.yaml'))
else:
md = Path(path) / "metadata.yaml"
if not md.exists():
return None
data = yaml.safe_load(md.open())
except yaml.YAMLError as exc:
if hasattr(exc, "problem_mark"):
mark = exc.problem_mark
Expand Down
Loading