Add integration between pol and mysql charms 81/10781/4
authorDavid Garcia <david.garcia@canonical.com>
Mon, 10 May 2021 10:59:33 +0000 (12:59 +0200)
committerbeierlm <mark.beierl@canonical.com>
Mon, 10 May 2021 18:35:56 +0000 (20:35 +0200)
- Added mysql_uri config in POL charm
- Added mysql relation endpoint in POL charm

Change-Id: I7983c1b83da6d894af864669b918215611848bf7
Signed-off-by: David Garcia <david.garcia@canonical.com>
installers/charm/bundles/osm-ha/bundle.yaml
installers/charm/bundles/osm/bundle.yaml
installers/charm/pol/config.yaml
installers/charm/pol/metadata.yaml
installers/charm/pol/src/charm.py
installers/charm/pol/tests/test_charm.py

index 0843115..b1804b8 100644 (file)
@@ -216,3 +216,5 @@ relations:
     - nbi:nbi
   - - mon:keystone
     - keystone:keystone
     - nbi:nbi
   - - mon:keystone
     - keystone:keystone
+  - - mariadb-k8s:mysql
+    - pol:mysql
index 824ff4c..bc0c400 100644 (file)
@@ -209,3 +209,5 @@ relations:
     - nbi:nbi
   - - mon:keystone
     - keystone:keystone
     - nbi:nbi
   - - mon:keystone
     - keystone:keystone
+  - - mariadb-k8s:mysql
+    - pol:mysql
index 59f695b..909235e 100644 (file)
@@ -27,3 +27,8 @@ options:
   mongodb_uri:
     type: string
     description: MongoDB URI (external database)
   mongodb_uri:
     type: string
     description: MongoDB URI (external database)
+  mysql_uri:
+    type: string
+    description: |
+      Mysql URI with the following format:
+        mysql://<user>:<password>@<mysql_host>:<mysql_port>/<database>
index f9839b9..e01293b 100644 (file)
@@ -43,3 +43,6 @@ requires:
     interface: kafka
   mongodb:
     interface: mongodb
     interface: kafka
   mongodb:
     interface: mongodb
+  mysql:
+    interface: mysql
+    limit: 1
index b2e5883..1ad1e26 100755 (executable)
 
 
 import logging
 
 
 import logging
+import re
 from typing import NoReturn, Optional
 
 from ops.main import main
 from opslib.osm.charm import CharmedOsmBase, RelationsMissing
 from opslib.osm.interfaces.kafka import KafkaClient
 from opslib.osm.interfaces.mongo import MongoClient
 from typing import NoReturn, Optional
 
 from ops.main import main
 from opslib.osm.charm import CharmedOsmBase, RelationsMissing
 from opslib.osm.interfaces.kafka import KafkaClient
 from opslib.osm.interfaces.mongo import MongoClient
+from opslib.osm.interfaces.mysql import MysqlClient
 from opslib.osm.pod import (
     ContainerV3Builder,
     PodSpecV3Builder,
 from opslib.osm.pod import (
     ContainerV3Builder,
     PodSpecV3Builder,
@@ -40,11 +42,13 @@ from opslib.osm.validator import ModelValidator, validator
 logger = logging.getLogger(__name__)
 
 PORT = 9999
 logger = logging.getLogger(__name__)
 
 PORT = 9999
+DEFAULT_MYSQL_DATABASE = "pol"
 
 
 class ConfigModel(ModelValidator):
     log_level: str
     mongodb_uri: Optional[str]
 
 
 class ConfigModel(ModelValidator):
     log_level: str
     mongodb_uri: Optional[str]
+    mysql_uri: Optional[str]
 
     @validator("log_level")
     def validate_log_level(cls, v):
 
     @validator("log_level")
     def validate_log_level(cls, v):
@@ -58,6 +62,13 @@ class ConfigModel(ModelValidator):
             raise ValueError("mongodb_uri is not properly formed")
         return v
 
             raise ValueError("mongodb_uri is not properly formed")
         return v
 
+    @validator("mysql_uri")
+    def validate_mysql_uri(cls, v):
+        pattern = re.compile("^mysql:\/\/.*:.*@.*:\d+\/.*$")  # noqa: W605
+        if v and not pattern.search(v):
+            raise ValueError("mysql_uri is not properly formed")
+        return v
+
 
 class PolCharm(CharmedOsmBase):
     def __init__(self, *args) -> NoReturn:
 
 class PolCharm(CharmedOsmBase):
     def __init__(self, *args) -> NoReturn:
@@ -71,6 +82,10 @@ class PolCharm(CharmedOsmBase):
         self.framework.observe(self.on["mongodb"].relation_changed, self.configure_pod)
         self.framework.observe(self.on["mongodb"].relation_broken, self.configure_pod)
 
         self.framework.observe(self.on["mongodb"].relation_changed, self.configure_pod)
         self.framework.observe(self.on["mongodb"].relation_broken, self.configure_pod)
 
+        self.mysql_client = MysqlClient(self, "mysql")
+        self.framework.observe(self.on["mysql"].relation_changed, self.configure_pod)
+        self.framework.observe(self.on["mysql"].relation_broken, self.configure_pod)
+
     def _check_missing_dependencies(self, config: ConfigModel):
         missing_relations = []
 
     def _check_missing_dependencies(self, config: ConfigModel):
         missing_relations = []
 
@@ -78,7 +93,8 @@ class PolCharm(CharmedOsmBase):
             missing_relations.append("kafka")
         if not config.mongodb_uri and self.mongodb_client.is_missing_data_in_unit():
             missing_relations.append("mongodb")
             missing_relations.append("kafka")
         if not config.mongodb_uri and self.mongodb_client.is_missing_data_in_unit():
             missing_relations.append("mongodb")
-
+        if not config.mysql_uri and self.mysql_client.is_missing_data_in_unit():
+            missing_relations.append("mysql")
         if missing_relations:
             raise RelationsMissing(missing_relations)
 
         if missing_relations:
             raise RelationsMissing(missing_relations)
 
@@ -88,6 +104,8 @@ class PolCharm(CharmedOsmBase):
 
         if config.mongodb_uri and not self.mongodb_client.is_missing_data_in_unit():
             raise Exception("Mongodb data cannot be provided via config and relation")
 
         if config.mongodb_uri and not self.mongodb_client.is_missing_data_in_unit():
             raise Exception("Mongodb data cannot be provided via config and relation")
+        if config.mysql_uri and not self.mysql_client.is_missing_data_in_unit():
+            raise Exception("Mysql data cannot be provided via config and relation")
 
         # Check relations
         self._check_missing_dependencies(config)
 
         # Check relations
         self._check_missing_dependencies(config)
@@ -111,6 +129,8 @@ class PolCharm(CharmedOsmBase):
                 "OSMPOL_DATABASE_DRIVER": "mongo",
                 "OSMPOL_DATABASE_URI": config.mongodb_uri
                 or self.mongodb_client.connection_string,
                 "OSMPOL_DATABASE_DRIVER": "mongo",
                 "OSMPOL_DATABASE_URI": config.mongodb_uri
                 or self.mongodb_client.connection_string,
+                "OSMPOL_SQL_DATABASE_URI": config.mysql_uri
+                or self.mysql_client.get_root_uri(DEFAULT_MYSQL_DATABASE),
             }
         )
         container = container_builder.build()
             }
         )
         container = container_builder.build()
index 089b6e5..330ecee 100644 (file)
@@ -74,6 +74,7 @@ class TestCharm(unittest.TestCase):
         self,
     ) -> NoReturn:
         "Test with relations and mongodb config (internal)"
         self,
     ) -> NoReturn:
         "Test with relations and mongodb config (internal)"
+        self.initialize_mysql_relation()
         self.initialize_kafka_relation()
         self.initialize_mongo_config()
         # Verifying status
         self.initialize_kafka_relation()
         self.initialize_mongo_config()
         # Verifying status
@@ -85,6 +86,7 @@ class TestCharm(unittest.TestCase):
         "Test with relations (internal)"
         self.initialize_kafka_relation()
         self.initialize_mongo_relation()
         "Test with relations (internal)"
         self.initialize_kafka_relation()
         self.initialize_mongo_relation()
+        self.initialize_mysql_relation()
         # Verifying status
         self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
 
         # Verifying status
         self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
 
@@ -97,6 +99,35 @@ class TestCharm(unittest.TestCase):
         # Verifying status
         self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
 
         # Verifying status
         self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
 
+    def test_mysql_config_success(self):
+        self.initialize_kafka_relation()
+        self.initialize_mongo_relation()
+        self.initialize_mysql_config()
+        # Verifying status
+        self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
+
+    def test_mysql_config_wrong_value(self):
+        self.initialize_kafka_relation()
+        self.initialize_mongo_relation()
+        self.initialize_mysql_config(uri="wrong_uri")
+        # Verifying status
+        self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
+        self.assertIn(
+            "mysql_uri is not properly formed",
+            self.harness.charm.unit.status.message,
+        )
+
+    def test_mysql_config_and_relation(self):
+        self.initialize_mysql_relation()
+        self.initialize_mysql_config()
+        # Verifying status
+        self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
+        # import pdb; pdb.set_trace()
+        self.assertIn(
+            "Mysql data cannot be provided via config and relation",
+            self.harness.charm.unit.status.message,
+        )
+
     def initialize_kafka_relation(self):
         kafka_relation_id = self.harness.add_relation("kafka", "kafka")
         self.harness.add_relation_unit(kafka_relation_id, "kafka/0")
     def initialize_kafka_relation(self):
         kafka_relation_id = self.harness.add_relation("kafka", "kafka")
         self.harness.add_relation_unit(kafka_relation_id, "kafka/0")
@@ -116,6 +147,27 @@ class TestCharm(unittest.TestCase):
             {"connection_string": "mongodb://mongo:27017"},
         )
 
             {"connection_string": "mongodb://mongo:27017"},
         )
 
+    def initialize_mysql_config(self, uri=None):
+        self.harness.update_config(
+            {"mysql_uri": uri or "mysql://user:pass@mysql-host:3306/database"}
+        )
+
+    def initialize_mysql_relation(self):
+        mongodb_relation_id = self.harness.add_relation("mysql", "mysql")
+        self.harness.add_relation_unit(mongodb_relation_id, "mysql/0")
+        self.harness.update_relation_data(
+            mongodb_relation_id,
+            "mysql/0",
+            {
+                "user": "user",
+                "password": "pass",
+                "host": "host",
+                "port": "1234",
+                "database": "pol",
+                "root_password": "root_password",
+            },
+        )
+
 
 if __name__ == "__main__":
     unittest.main()
 
 if __name__ == "__main__":
     unittest.main()