from juju.client import client
from juju import tag
+from n2vc.definitions import Offer, RelationEndpoint
from n2vc.juju_watcher import JujuModelWatcher
from n2vc.provisioner import AsyncSSHProvisioner
from n2vc.n2vc_conn import N2VCConnector
controller = await self.get_controller()
model = await self.get_model(controller, model_name)
try:
- await model.deploy(uri)
+ await model.deploy(uri, trust=True)
if wait:
await JujuModelWatcher.wait_for_model(model, timeout=timeout)
self.log.debug("All units active in model {}".format(model_name))
raise JujuApplicationExists(
"Application {} exists".format(application_name)
)
+ except juju.errors.JujuError as e:
+ if "already exists" in e.message:
+ raise JujuApplicationExists(
+ "Application {} exists".format(application_name)
+ )
+ else:
+ raise e
finally:
await self.disconnect_model(model)
await self.disconnect_controller(controller)
await self.disconnect_model(model)
await self.disconnect_controller(controller)
+ async def offer(self, endpoint: RelationEndpoint) -> Offer:
+ """
+ Create an offer from a RelationEndpoint
+
+ :param: endpoint: Relation endpoint
+
+ :return: Offer object
+ """
+ model_name = endpoint.model_name
+ offer_name = f"{endpoint.application_name}-{endpoint.endpoint_name}"
+ controller = await self.get_controller()
+ model = None
+ try:
+ model = await self.get_model(controller, model_name)
+ await model.create_offer(endpoint.endpoint, offer_name=offer_name)
+ offer_list = await self._list_offers(model_name, offer_name=offer_name)
+ if offer_list:
+ return Offer(offer_list[0].offer_url)
+ else:
+ raise Exception("offer was not created")
+ except juju.errors.JujuError as e:
+ if "application offer already exists" not in e.message:
+ raise e
+ finally:
+ if model:
+ self.disconnect_model(model)
+ self.disconnect_controller(controller)
+
async def consume(
self,
- offer_url: str,
model_name: str,
- ):
+ offer: Offer,
+ provider_libjuju: "Libjuju",
+ ) -> str:
"""
- Adds a remote offer to the model. Relations can be created later using "juju relate".
+ Consumes a remote offer in the model. Relations can be created later using "juju relate".
- :param: offer_url: Offer Url
- :param: model_name: Model name
+ :param: model_name: Model name
+ :param: offer: Offer object to consume
+ :param: provider_libjuju: Libjuju object of the provider endpoint
:raises ParseError if there's a problem parsing the offer_url
:raises JujuError if remote offer includes and endpoint
:raises JujuAPIError if the operation is not successful
+
+ :returns: Saas name. It is the application name in the model that reference the remote application.
"""
+ saas_name = f'{offer.name}-{offer.model_name.replace("-", "")}'
+ if offer.vca_id:
+ saas_name = f"{saas_name}-{offer.vca_id}"
controller = await self.get_controller()
- model = await controller.get_model(model_name)
-
+ model = None
+ provider_controller = None
try:
- await model.consume(offer_url)
+ model = await controller.get_model(model_name)
+ provider_controller = await provider_libjuju.get_controller()
+ await model.consume(
+ offer.url, application_alias=saas_name, controller=provider_controller
+ )
+ return saas_name
finally:
- await self.disconnect_model(model)
+ if model:
+ await self.disconnect_model(model)
+ if provider_controller:
+ await provider_libjuju.disconnect_controller(provider_controller)
await self.disconnect_controller(controller)
async def destroy_model(self, model_name: str, total_timeout: float = 1800):
finally:
await self.disconnect_controller(controller)
- async def list_offers(self, model_name: str) -> QueryApplicationOffersResults:
- """List models with certain names
+ async def _list_offers(
+ self, model_name: str, offer_name: str = None
+ ) -> QueryApplicationOffersResults:
+ """
+ List offers within a model
:param: model_name: Model name
+ :param: offer_name: Offer name to filter.
- :return: Returns list of offers
+ :return: Returns application offers results in the model
"""
controller = await self.get_controller()
try:
- return await controller.list_offers(model_name)
+ offers = (await controller.list_offers(model_name)).results
+ if offer_name:
+ matching_offer = []
+ for offer in offers:
+ if offer.offer_name == offer_name:
+ matching_offer.append(offer)
+ break
+ offers = matching_offer
+ return offers
finally:
await self.disconnect_controller(controller)