Fix Bug 2204 - Grafana Charm is failing to be deployed in Charmed OSM Master
[osm/devops.git] / installers / charm / grafana / src / charm.py
index e20a052..caa0277 100755 (executable)
@@ -39,6 +39,7 @@ from opslib.osm.pod import (
     ContainerV3Builder,
     FilesV3Builder,
     IngressResourceV3Builder,
+    PodRestartPolicy,
     PodSpecV3Builder,
 )
 from opslib.osm.validator import ModelValidator, validator
@@ -59,6 +60,7 @@ class ConfigModel(ModelValidator):
     ingress_whitelist_source_range: Optional[str]
     tls_secret_name: Optional[str]
     image_pull_policy: str
+    security_context: bool
 
     @validator("log_level")
     def validate_log_level(cls, v):
@@ -143,11 +145,25 @@ class GrafanaCharm(CharmedOsmBase):
 
     def _build_datasources_files(self):
         files_builder = FilesV3Builder()
+        prometheus_user = self.prometheus_client.user
+        prometheus_password = self.prometheus_client.password
+        enable_basic_auth = all([prometheus_user, prometheus_password])
+        kwargs = {
+            "prometheus_host": self.prometheus_client.hostname,
+            "prometheus_port": self.prometheus_client.port,
+            "enable_basic_auth": enable_basic_auth,
+            "user": "",
+            "password": "",
+        }
+        if enable_basic_auth:
+            kwargs["user"] = f"basic_auth_user: {prometheus_user}"
+            kwargs[
+                "password"
+            ] = f"secure_json_data:\n      basicAuthPassword: {prometheus_password}"
         files_builder.add_file(
             "datasource_prometheus.yaml",
             Template(Path("templates/default_datasources.yaml").read_text()).substitute(
-                prometheus_host=self.prometheus_client.hostname,
-                prometheus_port=self.prometheus_client.port,
+                **kwargs
             ),
         )
         return files_builder.build()
@@ -182,11 +198,28 @@ class GrafanaCharm(CharmedOsmBase):
             self.grafana_cluster.set_initial_password(admin_initial_password)
 
         # Create Builder for the PodSpec
-        pod_spec_builder = PodSpecV3Builder()
+        pod_spec_builder = PodSpecV3Builder(
+            enable_security_context=config.security_context
+        )
+
+        # Add secrets to the pod
+        grafana_secret_name = f"{self.app.name}-admin-secret"
+        pod_spec_builder.add_secret(
+            grafana_secret_name,
+            {
+                "admin-password": admin_initial_password,
+                "mysql-url": mysql_config.mysql_uri or self.mysql_client.get_uri(),
+                "prometheus-user": self.prometheus_client.user,
+                "prometheus-password": self.prometheus_client.password,
+            },
+        )
 
         # Build Container
         container_builder = ContainerV3Builder(
-            self.app.name, image_info, config.image_pull_policy
+            self.app.name,
+            image_info,
+            config.image_pull_policy,
+            run_as_non_root=config.security_context,
         )
         container_builder.add_port(name=self.app.name, port=config.port)
         container_builder.add_http_readiness_probe(
@@ -214,30 +247,30 @@ class GrafanaCharm(CharmedOsmBase):
             "/etc/grafana/provisioning/datasources/",
             self._build_datasources_files(),
         )
-
         container_builder.add_envs(
             {
                 "GF_SERVER_HTTP_PORT": config.port,
                 "GF_LOG_LEVEL": config.log_level,
                 "GF_SECURITY_ADMIN_USER": config.admin_user,
-                "GF_SECURITY_ADMIN_PASSWORD": {
-                    "secret": {"name": "grafana-admin-secret", "key": "admin-password"}
-                },
-                "GF_DATABASE_URL": {
-                    "secret": {"name": "grafana-admin-secret", "key": "mysql-url"}
-                },
+            }
+        )
+        container_builder.add_secret_envs(
+            secret_name=grafana_secret_name,
+            envs={
+                "GF_SECURITY_ADMIN_PASSWORD": "admin-password",
+                "GF_DATABASE_URL": "mysql-url",
+                "PROMETHEUS_USER": "prometheus-user",
+                "PROMETHEUS_PASSWORD": "prometheus-password",
             },
         )
         container = container_builder.build()
-        # Add container to pod spec
         pod_spec_builder.add_container(container)
-        pod_spec_builder.add_secret(
-            "grafana-admin-secret",
-            {
-                "admin-password": admin_initial_password,
-                "mysql-url": mysql_config.mysql_uri or self.mysql_client.get_uri(),
-            },
-        )
+
+        # Add Pod restart policy
+        restart_policy = PodRestartPolicy()
+        restart_policy.add_secrets(secret_names=(grafana_secret_name,))
+        pod_spec_builder.set_restart_policy(restart_policy)
+
         # Add ingress resources to pod spec if site url exists
         if config.site_url:
             parsed = urlparse(config.site_url)