Pylibjuju 2.9.46.0 Release Notes

The Juju team is proud to release Pylibjuju 2.9.46.0!

Pylibjuju enables you to drive Juju from Python, easing operations from day 2 and beyond. It is a toolkit for adding automation to your projects. Pylibjuju enables you to manage your Juju controllers, models, applications and units.

How do I get it?

The best way to get your hands on this release of Pylibjuju is to use pypi:

pip install juju

What’s Changed

This is a release of the Pylibjuju 2.9 track. A smaller release with only one bug fix. Works with the latest Juju 2.9.46 (and earlier 2.9 versions).

Feedback Appreciated!

We encourage everyone to let us know how you’re using Pylibjuju. Please ask questions on on Discourse, send us a message on Twitter using the hashtag #jujucharms.

I’m going to take my first stab at this again. I tried many years ago but failed. Now I want to try to develop some business logic and need to extract information from multiple controllers to populate data in another database.

It would be interesting if there is some code already written that does something similar @cderici

Would you be able to assist?

I ran in to issues which is likely because I don’t know how to use this.

  • I have a local client which I’ve registered against the controller which works.
  • I have the user and

I have this code.

from juju import jasyncio
from juju.model import Model

async def status():
    model = Model()
    await model.connect(model_name='local-lxd:admin/tutorial', username='erik-local', password='123456789')

    status = await model.get_status()
    await model.disconnect()

    print('Applications:', list(status.applications.keys()))
    print('Machines:', list(status.machines.keys()))
    print('Relations:', status.relations)

    return status

if __name__ == '__main__':
    jasyncio.run(status())

When I try to run it I get SSL problems:

requests.exceptions.SSLError: HTTPSConnectionPool(host=‘10.51.45.220’, port=17070): Max retries exceeded with url: /auth/discharge (Caused by SSLError(SSLCertVerificationError(1, ‘[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain (_ssl.c:1007)’)))

I have more questions which I would love to know how to deal with later =)

juju==2.9.46.0 juju controller = 2.9.46 Python 3.10.12

I have tried to include the cacert in the connect and extracted the certificate from my controllers.yaml.

controllerCAcrt = """
----BEGIN CERTIFICATE-----
..........
-----END CERTIFICATE-----
"""

and included it in my connect()

await model.connect(model_name='local-lxd:admin/tutorial', username='erik-local', password='123456789', cacert=controllerCAcrt)

But no luck.

requests.exceptions.SSLError: HTTPSConnectionPool(host='10.51.45.220', port=17070): Max retries exceeded with url: /auth/discharge (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain (_ssl.c:1007)')))

So I then tried copy the cacert to

/usr/local/share/ca-certificates/juju-local-lxd-controller-ca.crt

Then ran:

sudo update-ca-certificates
Updating certificates in /etc/ssl/certs...
rehash: warning: skipping ca-certificates.crt,it does not contain exactly one certificate or CRL
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.

Then tried the code again:

root@libjuju:~# python3 smalltest.py 
Traceback (most recent call last):
  File "/root/smalltest.py", line 49, in <module>
    jasyncio.run(status())
  File "/usr/local/lib/python3.10/dist-packages/juju/jasyncio.py", line 120, in run
    raise task.exception()
  File "/root/smalltest.py", line 37, in status
    await model.connect(model_name='local-lxd:admin/tutorial', username='erik-local', password='123456789', cacert=cacert)
  File "/usr/local/lib/python3.10/dist-packages/juju/model.py", line 703, in connect
    await self._connector.connect_model(model_name, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/juju/client/connector.py", line 184, in connect_model
    await self.connect(**kwargs)
  File "/usr/local/lib/python3.10/dist-packages/juju/client/connector.py", line 83, in connect
    self._connection = await Connection.connect(**kwargs)
  File "/usr/local/lib/python3.10/dist-packages/juju/client/connection.py", line 343, in connect
    await self._connect_with_redirect([_ep])
  File "/usr/local/lib/python3.10/dist-packages/juju/client/connection.py", line 862, in _connect_with_redirect
    login_result = await self._connect_with_login(endpoints)
  File "/usr/local/lib/python3.10/dist-packages/juju/client/connection.py", line 841, in _connect_with_login
    self.bakery_client.handle_error(
  File "/usr/local/lib/python3.10/dist-packages/macaroonbakery/httpbakery/_client.py", line 101, in handle_error
    discharges = bakery.discharge_all(
  File "/usr/local/lib/python3.10/dist-packages/macaroonbakery/bakery/_discharge.py", line 77, in discharge_all
    dm = get_discharge(cav.cav, cav.encrypted_caveat)
  File "/usr/local/lib/python3.10/dist-packages/macaroonbakery/httpbakery/_client.py", line 151, in acquire_discharge
    token, m = self._interact(loc, cause, payload)
  File "/usr/local/lib/python3.10/dist-packages/macaroonbakery/httpbakery/_client.py", line 209, in _interact
    raise InteractionError('no supported interaction method')
macaroonbakery.httpbakery._error.InteractionError: cannot start interactive session: no supported interaction method

So, still no luck.

So, then I realized that I needed to pass alot more information to be able to call the function properly with endpoint and uuid.

await model.connect(endpoint="10.51.45.220:17070", uuid="b0d6bad3-6c1e-461b-85a4-c7b83dc4675e", username='erik-local', password='123456789', cacert=cacert)

Then it worked out!

root@libjuju:~# python3 smalltest.py 
Applications: ['microsample-observed']
Machines: ['1', '2']
Relations: []

This experience could have been much more pleasant with some more explicit examples. =)