Improve logs for K8sJujuConnector init_env
[osm/N2VC.git] / n2vc / k8s_juju_conn.py
index 149947d..1704ec0 100644 (file)
@@ -20,6 +20,7 @@ import tempfile
 import binascii
 
 from n2vc.config import EnvironConfig
+from n2vc.definitions import RelationEndpoint
 from n2vc.exceptions import K8sException
 from n2vc.k8s_conn import K8sConnector
 from n2vc.kubectl import Kubectl
@@ -121,14 +122,16 @@ class K8sJujuConnector(K8sConnector):
         # if it fails in the middle of the process
         cleanup_data = []
         try:
+            self.log.debug("Initializing K8s cluster for juju")
             kubectl.create_cluster_role(
                 name=metadata_name,
                 labels=labels,
             )
+            self.log.debug("Cluster role created")
             cleanup_data.append(
                 {
                     "delete": kubectl.delete_cluster_role,
-                    "args": (metadata_name),
+                    "args": (metadata_name,),
                 }
             )
 
@@ -136,10 +139,11 @@ class K8sJujuConnector(K8sConnector):
                 name=metadata_name,
                 labels=labels,
             )
+            self.log.debug("Service account created")
             cleanup_data.append(
                 {
                     "delete": kubectl.delete_service_account,
-                    "args": (metadata_name),
+                    "args": (metadata_name,),
                 }
             )
 
@@ -147,10 +151,11 @@ class K8sJujuConnector(K8sConnector):
                 name=metadata_name,
                 labels=labels,
             )
+            self.log.debug("Role binding created")
             cleanup_data.append(
                 {
                     "delete": kubectl.delete_service_account,
-                    "args": (metadata_name),
+                    "args": (metadata_name,),
                 }
             )
             token, client_cert_data = await kubectl.get_secret_data(
@@ -158,6 +163,7 @@ class K8sJujuConnector(K8sConnector):
             )
 
             default_storage_class = kubectl.get_default_storage_class()
+            self.log.debug("Default storage class: {}".format(default_storage_class))
             await libjuju.add_k8s(
                 name=cluster_uuid,
                 rbac_id=rbac_id,
@@ -167,9 +173,10 @@ class K8sJujuConnector(K8sConnector):
                 storage_class=default_storage_class,
                 credential_name=self._get_credential_name(cluster_uuid),
             )
+            self.log.debug("K8s cluster added to juju controller")
             return cluster_uuid, True
         except Exception as e:
-            self.log.error("Error initializing k8scluster: {}".format(e))
+            self.log.error("Error initializing k8scluster: {}".format(e), exc_info=True)
             if len(cleanup_data) > 0:
                 self.log.debug("Cleaning up created resources in k8s cluster...")
                 for item in cleanup_data:
@@ -302,6 +309,10 @@ class K8sJujuConnector(K8sConnector):
             raise K8sException("bundle must be set")
 
         if bundle.startswith("cs:"):
+            # For Juju Bundles provided by the Charm Store
+            pass
+        elif bundle.startswith("ch:"):
+            # For Juju Bundles provided by the Charm Hub (this only works for juju version >= 2.9)
             pass
         elif bundle.startswith("http"):
             # Download the file
@@ -359,8 +370,8 @@ class K8sJujuConnector(K8sConnector):
         """Scale an application in a model
 
         :param: kdu_instance str:        KDU instance name
-        :param: scale int:               Scale to which to set this application
-        :param: resource_name str:       Resource name (Application name)
+        :param: scale int:               Scale to which to set the application
+        :param: resource_name str:       The application name in the Juju Bundle
         :param: timeout float:           The time, in seconds, to wait for the install
                                          to finish
         :param kwargs:                   Additional parameters
@@ -393,12 +404,13 @@ class K8sJujuConnector(K8sConnector):
     ) -> int:
         """Get an application scale count
 
-        :param: resource_name str:       Resource name (Application name)
+        :param: resource_name str:       The application name in the Juju Bundle
         :param: kdu_instance str:        KDU instance name
         :param kwargs:                   Additional parameters
                                             vca_id (str): VCA ID
         :return: Return application instance count
         """
+
         try:
             libjuju = await self._get_libjuju(kwargs.get("vca_id"))
             status = await libjuju.get_model_status(kdu_instance)
@@ -673,6 +685,53 @@ class K8sJujuConnector(K8sConnector):
 
         return status
 
+    async def add_relation(
+        self,
+        provider: RelationEndpoint,
+        requirer: RelationEndpoint,
+    ):
+        """
+        Add relation between two charmed endpoints
+
+        :param: provider: Provider relation endpoint
+        :param: requirer: Requirer relation endpoint
+        """
+        self.log.debug(f"adding new relation between {provider} and {requirer}")
+        cross_model_relation = (
+            provider.model_name != requirer.model_name
+            or requirer.vca_id != requirer.vca_id
+        )
+        try:
+            if cross_model_relation:
+                # Cross-model relation
+                provider_libjuju = await self._get_libjuju(provider.vca_id)
+                requirer_libjuju = await self._get_libjuju(requirer.vca_id)
+                offer = await provider_libjuju.offer(provider)
+                if offer:
+                    saas_name = await requirer_libjuju.consume(
+                        requirer.model_name, offer, provider_libjuju
+                    )
+                    await requirer_libjuju.add_relation(
+                        requirer.model_name,
+                        requirer.endpoint,
+                        saas_name,
+                    )
+            else:
+                # Standard relation
+                vca_id = provider.vca_id
+                model = provider.model_name
+                libjuju = await self._get_libjuju(vca_id)
+                # add juju relations between two applications
+                await libjuju.add_relation(
+                    model_name=model,
+                    endpoint_1=provider.endpoint,
+                    endpoint_2=requirer.endpoint,
+                )
+        except Exception as e:
+            message = f"Error adding relation between {provider} and {requirer}: {e}"
+            self.log.error(message)
+            raise Exception(message=message)
+
     async def update_vca_status(self, vcastatus: dict, kdu_instance: str, **kwargs):
         """
         Add all configs, actions, executed actions of all applications in a model to vcastatus dict