Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update charm libraries #268

Merged
merged 2 commits into from
Jan 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 25 additions & 13 deletions lib/charms/observability_libs/v0/cert_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@

LIBID = "b5cd5cd580f3428fa5f59a8876dcbe6a"
LIBAPI = 0
LIBPATCH = 8
LIBPATCH = 9


def is_ip_address(value: str) -> bool:
Expand Down Expand Up @@ -181,33 +181,40 @@ def _peer_relation(self) -> Optional[Relation]:
return self.charm.model.get_relation(self.peer_relation_name, None)

def _on_peer_relation_created(self, _):
"""Generate the private key and store it in a peer relation."""
# We're in "relation-created", so the relation should be there
"""Generate the CSR if the certificates relation is ready."""
self._generate_privkey()

# Just in case we already have a private key, do not overwrite it.
# Not sure how this could happen.
# TODO figure out how to go about key rotation.
if not self._private_key:
private_key = generate_private_key()
self._private_key = private_key.decode()

# Generate CSR here, in case peer events fired after tls-certificate relation events
# check cert relation is ready
if not (self.charm.model.get_relation(self.certificates_relation_name)):
# peer relation event happened to fire before tls-certificates events.
# Abort, and let the "certificates joined" observer create the CSR.
logger.info("certhandler waiting on certificates relation")
return

logger.debug("certhandler has peer and certs relation: proceeding to generate csr")
self._generate_csr()

def _on_certificates_relation_joined(self, _) -> None:
"""Generate the CSR and request the certificate creation."""
"""Generate the CSR if the peer relation is ready."""
self._generate_privkey()

# check peer relation is there
if not self._peer_relation:
# tls-certificates relation event happened to fire before peer events.
# Abort, and let the "peer joined" relation create the CSR.
logger.info("certhandler waiting on peer relation")
return

logger.debug("certhandler has peer and certs relation: proceeding to generate csr")
self._generate_csr()

def _generate_privkey(self):
# Generate priv key unless done already
# TODO figure out how to go about key rotation.
if not self._private_key:
private_key = generate_private_key()
self._private_key = private_key.decode()

def _on_config_changed(self, _):
# FIXME on config changed, the web_external_url may or may not change. But because every
# call to `generate_csr` appends a uuid, CSRs cannot be easily compared to one another.
Expand Down Expand Up @@ -237,7 +244,12 @@ def _generate_csr(
# In case we already have a csr, do not overwrite it by default.
if overwrite or renew or not self._csr:
private_key = self._private_key
assert private_key is not None # for type checker
if private_key is None:
# FIXME: raise this in a less nested scope by
# generating privkey and csr in the same method.
raise RuntimeError(
"private key unset. call _generate_privkey() before you call this method."
)
csr = generate_csr(
private_key=private_key.encode(),
subject=self.cert_subject,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def setUp(self, *unused):
from math import ceil, floor
from typing import Callable, Dict, List, Optional, Union

from lightkube import ApiError, Client
from lightkube import ApiError, Client # pyright: ignore
from lightkube.core import exceptions
from lightkube.models.apps_v1 import StatefulSetSpec
from lightkube.models.core_v1 import (
Expand All @@ -133,7 +133,7 @@ def setUp(self, *unused):

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


_Decimal = Union[Decimal, float, str, int] # types that are potentially convertible to Decimal
Expand Down Expand Up @@ -322,7 +322,7 @@ def __init__(self, namespace: str, statefulset_name: str, container_name: str):
self.namespace = namespace
self.statefulset_name = statefulset_name
self.container_name = container_name
self.client = Client()
self.client = Client() # pyright: ignore

def _patched_delta(self, resource_reqs: ResourceRequirements) -> StatefulSet:
statefulset = self.client.get(
Expand Down Expand Up @@ -421,7 +421,7 @@ def apply(self, resource_reqs: ResourceRequirements) -> None:
class KubernetesComputeResourcesPatch(Object):
"""A utility for patching the Kubernetes compute resources set up by Juju."""

on = K8sResourcePatchEvents()
on = K8sResourcePatchEvents() # pyright: ignore

def __init__(
self,
Expand Down
28 changes: 17 additions & 11 deletions lib/charms/prometheus_k8s/v0/prometheus_scrape.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ def _on_scrape_targets_changed(self, event):

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

PYDEPS = ["cosl"]

Expand All @@ -386,6 +386,7 @@ def _on_scrape_targets_changed(self, event):
"basic_auth",
"tls_config",
"authorization",
"params",
}
DEFAULT_JOB = {
"metrics_path": "/metrics",
Expand Down Expand Up @@ -764,7 +765,7 @@ def _validate_relation_by_interface_and_direction(
actual_relation_interface = relation.interface_name
if actual_relation_interface != expected_relation_interface:
raise RelationInterfaceMismatchError(
relation_name, expected_relation_interface, actual_relation_interface
relation_name, expected_relation_interface, actual_relation_interface or "None"
)

if expected_relation_role == RelationRole.provides:
Expand Down Expand Up @@ -857,7 +858,7 @@ class MonitoringEvents(ObjectEvents):
class MetricsEndpointConsumer(Object):
"""A Prometheus based Monitoring service."""

on = MonitoringEvents()
on = MonitoringEvents() # pyright: ignore

def __init__(self, charm: CharmBase, relation_name: str = DEFAULT_RELATION_NAME):
"""A Prometheus based Monitoring service.
Expand Down Expand Up @@ -1014,7 +1015,6 @@ def alerts(self) -> dict:
try:
scrape_metadata = json.loads(relation.data[relation.app]["scrape_metadata"])
identifier = JujuTopology.from_dict(scrape_metadata).identifier
alerts[identifier] = self._tool.apply_label_matchers(alert_rules) # type: ignore

except KeyError as e:
logger.debug(
Expand All @@ -1029,6 +1029,10 @@ def alerts(self) -> dict:
)
continue

# We need to append the relation info to the identifier. This is to allow for cases for there are two
# relations which eventually scrape the same application. Issue #551.
identifier = f"{identifier}_{relation.name}_{relation.id}"

alerts[identifier] = alert_rules

_, errmsg = self._tool.validate_alert_rules(alert_rules)
Expand Down Expand Up @@ -1294,7 +1298,7 @@ def _resolve_dir_against_charm_path(charm: CharmBase, *path_elements: str) -> st
class MetricsEndpointProvider(Object):
"""A metrics endpoint for Prometheus."""

on = MetricsEndpointProviderEvents()
on = MetricsEndpointProviderEvents() # pyright: ignore

def __init__(
self,
Expand Down Expand Up @@ -1836,14 +1840,16 @@ def _set_prometheus_data(self, event):
return

jobs = [] + _type_convert_stored(
self._stored.jobs
self._stored.jobs # pyright: ignore
) # list of scrape jobs, one per relation
for relation in self.model.relations[self._target_relation]:
targets = self._get_targets(relation)
if targets and relation.app:
jobs.append(self._static_scrape_job(targets, relation.app.name))

groups = [] + _type_convert_stored(self._stored.alert_rules) # list of alert rule groups
groups = [] + _type_convert_stored(
self._stored.alert_rules # pyright: ignore
) # list of alert rule groups
for relation in self.model.relations[self._alert_rules_relation]:
unit_rules = self._get_alert_rules(relation)
if unit_rules and relation.app:
Expand Down Expand Up @@ -1895,7 +1901,7 @@ def set_target_job_data(self, targets: dict, app_name: str, **kwargs) -> None:
jobs.append(updated_job)
relation.data[self._charm.app]["scrape_jobs"] = json.dumps(jobs)

if not _type_convert_stored(self._stored.jobs) == jobs:
if not _type_convert_stored(self._stored.jobs) == jobs: # pyright: ignore
self._stored.jobs = jobs

def _on_prometheus_targets_departed(self, event):
Expand Down Expand Up @@ -1947,7 +1953,7 @@ def remove_prometheus_jobs(self, job_name: str, unit_name: Optional[str] = ""):

relation.data[self._charm.app]["scrape_jobs"] = json.dumps(jobs)

if not _type_convert_stored(self._stored.jobs) == jobs:
if not _type_convert_stored(self._stored.jobs) == jobs: # pyright: ignore
self._stored.jobs = jobs

def _job_name(self, appname) -> str:
Expand Down Expand Up @@ -2126,7 +2132,7 @@ def set_alert_rule_data(self, name: str, unit_rules: dict, label_rules: bool = T
groups.append(updated_group)
relation.data[self._charm.app]["alert_rules"] = json.dumps({"groups": groups})

if not _type_convert_stored(self._stored.alert_rules) == groups:
if not _type_convert_stored(self._stored.alert_rules) == groups: # pyright: ignore
self._stored.alert_rules = groups

def _on_alert_rules_departed(self, event):
Expand Down Expand Up @@ -2176,7 +2182,7 @@ def remove_alert_rules(self, group_name: str, unit_name: str) -> None:
json.dumps({"groups": groups}) if groups else "{}"
)

if not _type_convert_stored(self._stored.alert_rules) == groups:
if not _type_convert_stored(self._stored.alert_rules) == groups: # pyright: ignore
self._stored.alert_rules = groups

def _get_alert_rules(self, relation) -> dict:
Expand Down
Loading
Loading