Skip to content

Commit

Permalink
Merge pull request #964 from cderici/controller-name-by-endpoint
Browse files Browse the repository at this point in the history
#964

#### Description

This allows all kinds of connections to set the `controller_name` by default by looking up the `endpoints` in the `jujudata`.

Fixes #771

#### QA Steps

Manual QA should follow the steps described in #771.

Find the details of a controller you bootstrapped (any controller would do):

```sh
 $ juju show-controller --show-password
```

Grab the details there and plug them into either a script or in the repl (repl is awkward to use with the certificate):

```python
 c = Controller()
 await c.connect(endpoint="<ip>:17070", username="admin", password="admin_pass", cacert="ca_cert") # explicit connection with credential values
 # check the name
 print(c.controller_name)
```

All CI tests need to pass.

#### Notes & Discussion

JUJU-4781
  • Loading branch information
jujubot authored Oct 17, 2023
2 parents 4691c96 + 6e3d7b9 commit 3927969
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 5 deletions.
13 changes: 9 additions & 4 deletions juju/client/connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
import macaroonbakery.httpbakery as httpbakery
from juju.client.connection import Connection
from juju.client.gocookies import GoCookieJar, go_to_py_cookie
from juju.client.jujudata import FileJujuData
from juju.client.jujudata import FileJujuData, API_ENDPOINTS_KEY
from juju.client.proxy.factory import proxy_from_config
from juju.errors import JujuConnectionError, JujuError
from juju.errors import JujuConnectionError, JujuError, PylibjujuProgrammingError
from juju.client import client

log = logging.getLogger('connector')
Expand Down Expand Up @@ -82,6 +82,11 @@ async def connect(self, **kwargs):
await self._connection.close()
self._connection = await Connection.connect(**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'])

# Check if we support the target controller
if not self._connection.info['server-version'].startswith(SUPPORTED_JUJU_API_PREFIX):
raise JujuConnectionError("juju server-version %s not supported" % self._connection.info["server-version"])
Expand All @@ -108,7 +113,7 @@ async def connect_controller(self, controller_name=None, specified_facades=None)
raise JujuConnectionError('No current controller')

controller = self.jujudata.controllers()[controller_name]
endpoints = controller['api-endpoints']
endpoints = controller[API_ENDPOINTS_KEY]
accounts = self.jujudata.accounts().get(controller_name, {})

proxy = proxy_from_config(controller.get('proxy-config', None))
Expand Down Expand Up @@ -142,7 +147,7 @@ async def connect_model(self, model_name=None, **kwargs):
if controller is None:
raise JujuConnectionError('Controller {} not found'.format(
controller_name))
endpoints = controller['api-endpoints']
endpoints = controller[API_ENDPOINTS_KEY]
account = self.jujudata.accounts().get(controller_name, {})
models = self.jujudata.models().get(controller_name, {}).get('models',
{})
Expand Down
21 changes: 20 additions & 1 deletion juju/client/jujudata.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
import yaml
from juju import tag
from juju.client.gocookies import GoCookieJar
from juju.errors import JujuError
from juju.errors import JujuError, PylibjujuProgrammingError
from juju.utils import juju_config_dir

API_ENDPOINTS_KEY = 'api-endpoints'


class NoModelException(Exception):
pass
Expand Down Expand Up @@ -126,6 +128,23 @@ def load_credential(self, cloud, name=None):
except (KeyError, FileNotFoundError):
return None, None

def controller_name_by_endpoint(self, endpoint):
"""Finds the controller that has the given endpoints, returns the name.
:param str endpoint: The endpoint of the controller we're looking for
"""
for controller_name, controller in self.controllers().items():
if isinstance(endpoint, str):
if endpoint in controller[API_ENDPOINTS_KEY]:
return controller_name
elif isinstance(endpoint, list):
for e in endpoint:
if e in controller[API_ENDPOINTS_KEY]:
return controller_name
else:
raise PylibjujuProgrammingError()
raise JujuError(f'Unable to find controller with endpoint {endpoint}')

def controllers(self):
return self._load_yaml('controllers.yaml', 'controllers')

Expand Down
4 changes: 4 additions & 0 deletions juju/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ class JujuBackupError(JujuError):
pass


class PylibjujuProgrammingError(Exception):
pass


class JujuConfigError(JujuError):
"""Exception raised during processing a configuration key-value pair
in a config set for an application.
Expand Down

0 comments on commit 3927969

Please sign in to comment.