Skip to content

Commit

Permalink
Merge pull request #1009 from cderici/controller-name-not-found
Browse files Browse the repository at this point in the history
#1009

#### Description

`controllers.yaml` is read for the `controller_name` after a connection is established, and this creates a dependency on the juju-cli to be installed in the system, which is not required for pylibjuju.

Fixes #996 

#### QA Steps

Testing this requires a bit of stateful actions. I see two easy ways to test:

1. Use the integration test I added. 

Add `import pdb;pdb.set_trace()` right before the `new_cont.connect(` line, and run the integration test with `--pdb` as follows:

```
tox -e integration -- -- tests/integration/test_connection.py::test_connection_happy_path --pdb
```

Before continuing, go find the `controllers.yaml` and rename it to something else (sort of easier than removing juju-cli etc):

```
mv controllers.yaml controllers.yaml.tmp
```

Now continue in the pdb (`c`) to see if the new connection will be established without a problem.

2. Do what the integration test is doing manually in the repl:

```python
 $ python -m asyncio
>>> from juju import controller
>>> c=controller.Controller();await c.connect()
```

Stop at this point to rename the `controllers.yaml` file.

```python
>>> new_c=controller.Controller()
>>> await new_c.connect(endpoint=c.endpoint, username=c.username, password=c.password, cacert=c.cacert)
```

This should succeed.

Don't forget to rename your controllers.yaml back:

```
mv controllers.yaml.tmp controllers.yaml
```

#### Notes & Discussion

JUJU-5317
  • Loading branch information
jujubot authored Jan 23, 2024
2 parents beed55f + cb70f35 commit 4f38c4e
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 4 deletions.
8 changes: 6 additions & 2 deletions juju/client/connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from juju.client.gocookies import GoCookieJar, go_to_py_cookie
from juju.client.jujudata import FileJujuData, API_ENDPOINTS_KEY
from juju.client.proxy.factory import proxy_from_config
from juju.errors import JujuConnectionError, JujuError, PylibjujuProgrammingError
from juju.errors import JujuConnectionError, JujuError, PylibjujuProgrammingError, ControllerNameNotFound
from juju.client import client

log = logging.getLogger('connector')
Expand Down Expand Up @@ -97,7 +97,11 @@ async def connect(self, **kwargs):
if not self.controller_name:
if 'endpoint' not in kwargs:
raise PylibjujuProgrammingError("Please report this error to the maintainers.")
self.controller_name = self.jujudata.controller_name_by_endpoint(kwargs['endpoint'])
try:
self.controller_name = self.jujudata.controller_name_by_endpoint(kwargs['endpoint'])
except ControllerNameNotFound:
# It's ok because we might not have the juju cli (controllers.yaml)
pass

# Check if we support the target controller
if not self._connection.info['server-version'].startswith(SUPPORTED_JUJU_API_PREFIX):
Expand Down
8 changes: 6 additions & 2 deletions juju/client/jujudata.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import yaml
from juju import tag
from juju.client.gocookies import GoCookieJar
from juju.errors import JujuError, PylibjujuProgrammingError
from juju.errors import JujuError, PylibjujuProgrammingError, ControllerNameNotFound
from juju.utils import juju_config_dir

API_ENDPOINTS_KEY = 'api-endpoints'
Expand Down Expand Up @@ -133,7 +133,11 @@ def controller_name_by_endpoint(self, endpoint):
:param str endpoint: The endpoint of the controller we're looking for
"""
for controller_name, controller in self.controllers().items():
try:
contrs = self.controllers()
except FileNotFoundError:
raise ControllerNameNotFound()
for controller_name, controller in contrs.items():
if isinstance(endpoint, str):
if endpoint in controller[API_ENDPOINTS_KEY]:
return controller_name
Expand Down
4 changes: 4 additions & 0 deletions juju/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,7 @@ class JujuModelConfigError(JujuConfigError):

class AbstractMethodError(Exception):
pass


class ControllerNameNotFound(Exception):
pass
14 changes: 14 additions & 0 deletions tests/integration/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,20 @@
logger = logging.getLogger(__name__)


@base.bootstrapped
@pytest.mark.asyncio
async def test_connection_happy_path(event_loop):
async with base.CleanController() as contr:
conn = contr.connection()
new_cont = Controller()
await new_cont.connect(endpoint=conn.endpoint,
username=conn.username,
password=conn.password,
cacert=conn.cacert,
)
await new_cont.disconnect()


@base.bootstrapped
@pytest.mark.asyncio
async def test_monitor(event_loop):
Expand Down

0 comments on commit 4f38c4e

Please sign in to comment.