Skip to content

Commit

Permalink
Merge pull request #43 from canonical/gh_41_update_libs
Browse files Browse the repository at this point in the history
update libs
  • Loading branch information
DomFleischmann authored Aug 4, 2022
2 parents 2566d4e + 7e660ee commit 40ace08
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 67 deletions.
64 changes: 44 additions & 20 deletions charms/mlflow-server/lib/charms/grafana_k8s/v0/grafana_dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ def __init__(self, *args):

# Increment this PATCH version before using `charmcraft publish-lib` or reset
# to 0 if you are raising the major API version
LIBPATCH = 11
LIBPATCH = 13

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -541,17 +541,26 @@ def _convert_dashboard_fields(content: str) -> str:
datasources = {}
existing_templates = False

# If the dashboard has __inputs, get the names to replace them. These are stripped
# from reactive dashboards in GrafanaDashboardAggregator, but charm authors in
# newer charms may import them directly from the marketplace
if "__inputs" in dict_content:
for field in dict_content["__inputs"]:
if "type" in field and field["type"] == "datasource":
datasources[field["name"]] = field["pluginName"].lower()
del dict_content["__inputs"]

# If no existing template variables exist, just insert our own
if "templating" not in dict_content:
dict_content["templating"] = {"list": [d for d in TEMPLATE_DROPDOWNS]}
else:
# Otherwise, set a flag so we can go back later
existing_templates = True
for maybe in dict_content["templating"]["list"]:
for template_value in dict_content["templating"]["list"]:
# Build a list of `datasource_name`: `datasource_type` mappings
# The "query" field is actually "prometheus", "loki", "influxdb", etc
if "type" in maybe and maybe["type"] == "datasource":
datasources[maybe["name"]] = maybe["query"]
if "type" in template_value and template_value["type"] == "datasource":
datasources[template_value["name"]] = template_value["query"].lower()

# Put our own variables in the template
for d in TEMPLATE_DROPDOWNS:
Expand All @@ -563,7 +572,7 @@ def _convert_dashboard_fields(content: str) -> str:
return json.dumps(dict_content)


def _replace_template_fields(
def _replace_template_fields( # noqa: C901
dict_content: dict, datasources: dict, existing_templates: bool
) -> dict:
"""Make templated fields get cleaned up afterwards.
Expand All @@ -586,11 +595,17 @@ def _replace_template_fields(
#
# COS only knows about Prometheus and Loki.
for panel in panels:
if "datasource" not in panel:
if "datasource" not in panel or not panel.get("datasource", ""):
continue
if not existing_templates:
panel["datasource"] = "${prometheusds}"
else:
if panel["datasource"].lower() in replacements.values():
# Already a known template variable
continue
if not panel["datasource"]:
# Don't worry about null values
continue
# Strip out variable characters and maybe braces
ds = re.sub(r"(\$|\{|\})", "", panel["datasource"])
replacement = replacements.get(datasources[ds], "")
Expand Down Expand Up @@ -654,19 +669,25 @@ class GrafanaDashboardEvent(EventBase):
Enables us to set a clear status on the provider.
"""

def __init__(self, handle, error_message: str = "", valid: bool = False):
def __init__(self, handle, errors: List[Dict[str, str]] = [], valid: bool = False):
super().__init__(handle)
self.error_message = error_message
self.errors = errors
self.error_message = "; ".join([error["error"] for error in errors if "error" in error])
self.valid = valid

def snapshot(self) -> Dict:
"""Save grafana source information."""
return {"error_message": self.error_message, "valid": self.valid}
return {
"error_message": self.error_message,
"valid": self.valid,
"errors": json.dumps(self.errors),
}

def restore(self, snapshot):
"""Restore grafana source information."""
self.error_message = snapshot["error_message"]
self.valid = snapshot["valid"]
self.errors = json.loads(snapshot["errors"])


class GrafanaProviderEvents(ObjectEvents):
Expand Down Expand Up @@ -830,11 +851,12 @@ def _update_all_dashboards_from_dir(self, _: Optional[HookEvent] = None) -> None
del stored_dashboard_templates[dashboard_id]

# Path.glob uses fnmatch on the backend, which is pretty limited, so use a
# lambda for the filter
for path in filter(
lambda p: p.is_file and p.name.endswith((".json", ".json.tmpl", ".tmpl")),
Path(self._dashboards_path).glob("*"),
):
# custom function for the filter
def _is_dashbaord(p: Path) -> bool:
return p.is_file and p.name.endswith((".json", ".json.tmpl", ".tmpl"))

for path in filter(_is_dashbaord, Path(self._dashboards_path).glob("*")):
# path = Path(path)
id = "file:{}".format(path.stem)
stored_dashboard_templates[id] = self._content_to_dashboard_object(
_encode_dashboard_content(path.read_bytes())
Expand Down Expand Up @@ -1059,7 +1081,7 @@ def update_dashboards(self, relation: Optional[Relation] = None) -> None:
)

for relation in relations:
self._render_dashboards_and_signal_changed(relation) # type: ignore
self._render_dashboards_and_signal_changed(relation)

if changes:
self.on.dashboards_changed.emit()
Expand Down Expand Up @@ -1090,7 +1112,7 @@ def _render_dashboards_and_signal_changed(self, relation: Relation) -> bool: #
"""
other_app = relation.app

raw_data = relation.data[other_app].get("dashboards", {})
raw_data = relation.data[other_app].get("dashboards", {}) # type: ignore

if not raw_data:
logger.warning(
Expand Down Expand Up @@ -1498,10 +1520,12 @@ def _maybe_get_builtin_dashboards(self, event: RelationEvent) -> Dict:
)

if dashboards_path:
for path in filter(
lambda p: p.is_file and p.name.endswith((".json", ".json.tmpl", ".tmpl")),
Path(dashboards_path).glob("*"),
):

def _is_dashbaord(p: Path) -> bool:
return p.is_file and p.name.endswith((".json", ".json.tmpl", ".tmpl"))

for path in filter(_is_dashbaord, Path(dashboards_path).glob("*")):
# path = Path(path)
if event.app.name in path.name:
id = "file:{}".format(path.stem)
builtins[id] = self._content_to_dashboard_object(
Expand Down
Loading

0 comments on commit 40ace08

Please sign in to comment.