X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2FN2VC.git;a=blobdiff_plain;f=modules%2Flibjuju%2Fjuju%2Fclient%2Fjujudata.py;fp=modules%2Flibjuju%2Fjuju%2Fclient%2Fjujudata.py;h=0000000000000000000000000000000000000000;hp=8b844c28b63cafd737a0ae0f768cee1df2870312;hb=9d18c22a0dc9e295adda50601fc5e2f45d2c9b8a;hpb=19c5cfca317615597be6bf1051e9d2fa903adb97 diff --git a/modules/libjuju/juju/client/jujudata.py b/modules/libjuju/juju/client/jujudata.py deleted file mode 100644 index 8b844c2..0000000 --- a/modules/libjuju/juju/client/jujudata.py +++ /dev/null @@ -1,219 +0,0 @@ -import abc -import io -import os -import pathlib - -import juju.client.client as jujuclient -import yaml -from juju import tag -from juju.client.gocookies import GoCookieJar -from juju.errors import JujuError - - -class NoModelException(Exception): - pass - - -class JujuData: - __metaclass__ = abc.ABCMeta - - @abc.abstractmethod - def current_controller(self): - '''Return the current controller name''' - raise NotImplementedError() - - @abc.abstractmethod - def controllers(self): - '''Return all the currently known controllers as a dict - mapping controller name to a dict containing the - following string keys: - uuid: The UUID of the controller - api-endpoints: A list of host:port addresses for the controller. - ca-cert: the PEM-encoded CA cert of the controller (optional) - - This is compatible with the "controllers" entry in the YAML-unmarshaled data - stored in ~/.local/share/juju/controllers.yaml. - ''' - raise NotImplementedError() - - @abc.abstractmethod - def models(self): - '''Return all the currently known models as a dict - containing a key for each known controller, - each holding a dict value containing an optional "current-model" - key (the name of the current model for that controller, - if there is one), and a dict mapping fully-qualified - model names to a dict containing a "uuid" key with the - key for that model. - This is compatible with the YAML-unmarshaled data - stored in ~/.local/share/juju/models.yaml. - ''' - raise NotImplementedError() - - @abc.abstractmethod - def accounts(self): - '''Return the currently known accounts, as a dict - containing a key for each known controller, with - each value holding a dict with the following keys: - - user: The username to use when logging into the controller (str) - password: The password to use when logging into the controller (str, optional) - ''' - raise NotImplementedError() - - @abc.abstractmethod - def cookies_for_controller(self, controller_name): - '''Return the cookie jar to use when connecting to the - controller with the given name. - :return http.cookiejar.CookieJar - ''' - raise NotImplementedError() - - @abc.abstractmethod - def current_model(self, controller_name=None, model_only=False): - '''Return the current model, qualified by its controller name. - If controller_name is specified, the current model for - that controller will be returned. - If model_only is true, only the model name, not qualified by - its controller name, will be returned. - ''' - raise NotImplementedError() - - def parse_model(self, model): - """Split the given model_name into controller and model parts. - If the controller part is empty, the current controller will be used. - If the model part is empty, the current model will be used for - the controller. - The returned model name will always be qualified with a username. - :param model str: The model name to parse. - :return (str, str): The controller and model names. - """ - # TODO if model is empty, use $JUJU_MODEL environment variable. - if model and ':' in model: - # explicit controller given - controller_name, model_name = model.split(':') - else: - # use the current controller if one isn't explicitly given - controller_name = self.current_controller() - model_name = model - if not controller_name: - controller_name = self.current_controller() - if not model_name: - model_name = self.current_model(controller_name, model_only=True) - if not model_name: - raise NoModelException('no current model') - - if '/' not in model_name: - # model name doesn't include a user prefix, so add one - # by using the current user for the controller. - accounts = self.accounts().get(controller_name) - if accounts is None: - raise JujuError('No account found for controller {} '.format(controller_name)) - username = accounts.get('user') - if username is None: - raise JujuError('No username found for controller {}'.format(controller_name)) - model_name = username + "/" + model_name - - return controller_name, model_name - - -class FileJujuData(JujuData): - '''Provide access to the Juju client configuration files. - Any configuration file is read once and then cached.''' - def __init__(self): - self.path = os.environ.get('JUJU_DATA') or '~/.local/share/juju' - self.path = os.path.abspath(os.path.expanduser(self.path)) - # _loaded keeps track of the loaded YAML from - # the Juju data files so we don't need to load the same - # file many times. - self._loaded = {} - - def refresh(self): - '''Forget the cache of configuration file data''' - self._loaded = {} - - def current_controller(self): - '''Return the current controller name''' - return self._load_yaml('controllers.yaml', 'current-controller') - - def current_model(self, controller_name=None, model_only=False): - '''Return the current model, qualified by its controller name. - If controller_name is specified, the current model for - that controller will be returned. - - If model_only is true, only the model name, not qualified by - its controller name, will be returned. - ''' - # TODO respect JUJU_MODEL environment variable. - if not controller_name: - controller_name = self.current_controller() - if not controller_name: - raise JujuError('No current controller') - models = self.models()[controller_name] - if 'current-model' not in models: - return None - if model_only: - return models['current-model'] - return controller_name + ':' + models['current-model'] - - def load_credential(self, cloud, name=None): - """Load a local credential. - - :param str cloud: Name of cloud to load credentials from. - :param str name: Name of credential. If None, the default credential - will be used, if available. - :return: A CloudCredential instance, or None. - """ - try: - cloud = tag.untag('cloud-', cloud) - creds_data = self.credentials()[cloud] - if not name: - default_credential = creds_data.pop('default-credential', None) - default_region = creds_data.pop('default-region', None) # noqa - if default_credential: - name = creds_data['default-credential'] - elif len(creds_data) == 1: - name = list(creds_data)[0] - else: - return None, None - cred_data = creds_data[name] - auth_type = cred_data.pop('auth-type') - return name, jujuclient.CloudCredential( - auth_type=auth_type, - attrs=cred_data, - ) - except (KeyError, FileNotFoundError): - return None, None - - def controllers(self): - return self._load_yaml('controllers.yaml', 'controllers') - - def models(self): - return self._load_yaml('models.yaml', 'controllers') - - def accounts(self): - return self._load_yaml('accounts.yaml', 'controllers') - - def credentials(self): - return self._load_yaml('credentials.yaml', 'credentials') - - def _load_yaml(self, filename, key): - if filename in self._loaded: - # Data already exists in the cache. - return self._loaded[filename].get(key) - # TODO use the file lock like Juju does. - filepath = os.path.join(self.path, filename) - with io.open(filepath, 'rt') as f: - data = yaml.safe_load(f) - self._loaded[filename] = data - return data.get(key) - - def cookies_for_controller(self, controller_name): - f = pathlib.Path(self.path) / 'cookies' / (controller_name + '.json') - if not f.exists(): - f = pathlib.Path('~/.go-cookies').expanduser() - # TODO if neither cookie file exists, where should - # we create the cookies? - jar = GoCookieJar(str(f)) - jar.load() - return jar