Adding ImagePullPolicy config option to OSM Charms
[osm/devops.git] / installers / charm / pol / src / charm.py
index d339e1c..727ffbe 100755 (executable)
 
 
 import logging
 
 
 import logging
-from typing import NoReturn
+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 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,10 +42,14 @@ 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
 
 
 class ConfigModel(ModelValidator):
     log_level: str
+    mongodb_uri: Optional[str]
+    mysql_uri: Optional[str]
+    image_pull_policy: Optional[str]
 
     @validator("log_level")
     def validate_log_level(cls, v):
 
     @validator("log_level")
     def validate_log_level(cls, v):
@@ -51,6 +57,31 @@ class ConfigModel(ModelValidator):
             raise ValueError("value must be INFO or DEBUG")
         return v
 
             raise ValueError("value must be INFO or DEBUG")
         return v
 
+    @validator("mongoddb_uri")
+    def validate_mongodb_uri(cls, v):
+        if v and not v.startswith("mongodb://"):
+            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
+
+    @validator("image_pull_policy")
+    def validate_image_pull_policy(cls, v):
+        values = {
+            "always": "Always",
+            "ifnotpresent": "IfNotPresent",
+            "never": "Never",
+        }
+        v = v.lower()
+        if v not in values.keys():
+            raise ValueError("value must be always, ifnotpresent or never")
+        return values[v]
+
 
 class PolCharm(CharmedOsmBase):
     def __init__(self, *args) -> NoReturn:
 
 class PolCharm(CharmedOsmBase):
     def __init__(self, *args) -> NoReturn:
@@ -64,26 +95,41 @@ 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 = []
 
         if self.kafka_client.is_missing_data_in_unit():
             missing_relations.append("kafka")
     def _check_missing_dependencies(self, config: ConfigModel):
         missing_relations = []
 
         if self.kafka_client.is_missing_data_in_unit():
             missing_relations.append("kafka")
-        if self.mongodb_client.is_missing_data_in_unit():
+        if not config.mongodb_uri and self.mongodb_client.is_missing_data_in_unit():
             missing_relations.append("mongodb")
             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)
 
     def build_pod_spec(self, image_info):
         # Validate config
         config = ConfigModel(**dict(self.config))
         if missing_relations:
             raise RelationsMissing(missing_relations)
 
     def build_pod_spec(self, image_info):
         # Validate config
         config = ConfigModel(**dict(self.config))
+
+        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)
+
         # Create Builder for the PodSpec
         pod_spec_builder = PodSpecV3Builder()
         # Create Builder for the PodSpec
         pod_spec_builder = PodSpecV3Builder()
+
         # Build Container
         # Build Container
-        container_builder = ContainerV3Builder(self.app.name, image_info)
+        container_builder = ContainerV3Builder(
+            self.app.name, image_info, config.image_pull_policy
+        )
         container_builder.add_port(name=self.app.name, port=PORT)
         container_builder.add_envs(
             {
         container_builder.add_port(name=self.app.name, port=PORT)
         container_builder.add_envs(
             {
@@ -96,13 +142,17 @@ class PolCharm(CharmedOsmBase):
                 "OSMPOL_MESSAGE_PORT": self.kafka_client.port,
                 # Database configuration
                 "OSMPOL_DATABASE_DRIVER": "mongo",
                 "OSMPOL_MESSAGE_PORT": self.kafka_client.port,
                 # Database configuration
                 "OSMPOL_DATABASE_DRIVER": "mongo",
-                "OSMPOL_DATABASE_URI": self.mongodb_client.connection_string,
+                "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()
+
         # Add container to pod spec
         pod_spec_builder.add_container(container)
         # Add container to pod spec
         pod_spec_builder.add_container(container)
+
         return pod_spec_builder.build()
 
 
         return pod_spec_builder.build()