Skip to content

Commit

Permalink
chore: update charm libraries
Browse files Browse the repository at this point in the history
  • Loading branch information
Github Actions committed Jan 23, 2024
1 parent 3f0cc21 commit 006d759
Show file tree
Hide file tree
Showing 10 changed files with 458 additions and 216 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def _on_certificate_removed(self, event: CertificateRemovedEvent):
import logging
from typing import List

from jsonschema import exceptions, validate # type: ignore[import]
from jsonschema import exceptions, validate # type: ignore[import-untyped]
from ops.charm import CharmBase, CharmEvents, RelationBrokenEvent, RelationChangedEvent
from ops.framework import EventBase, EventSource, Handle, Object

Expand All @@ -109,7 +109,7 @@ def _on_certificate_removed(self, event: CertificateRemovedEvent):

# 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

PYDEPS = ["jsonschema"]

Expand Down
46 changes: 28 additions & 18 deletions lib/charms/loki_k8s/v0/loki_push_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
implement the provider side of the `loki_push_api` relation interface. For instance, a Loki charm.
The provider side of the relation represents the server side, to which logs are being pushed.
- `LokiPushApiConsumer`: This object is meant to be used by any Charmed Operator that needs to
send log to Loki by implementing the consumer side of the `loki_push_api` relation interface.
For instance, a Promtail or Grafana agent charm which needs to send logs to Loki.
- `LokiPushApiConsumer`: Used to obtain the loki api endpoint. This is useful for configuring
applications such as pebble, or charmed operators of workloads such as grafana-agent or promtail,
that can communicate with loki directly.
- `LogProxyConsumer`: This object can be used by any Charmed Operator which needs to
send telemetry, such as logs, to Loki through a Log Proxy by implementing the consumer side of the
Expand Down Expand Up @@ -456,7 +456,7 @@ def _alert_rules_error(self, event):
from urllib.error import HTTPError

import yaml
from charms.observability_libs.v0.juju_topology import JujuTopology
from cosl import JujuTopology
from ops.charm import (
CharmBase,
HookEvent,
Expand All @@ -480,7 +480,7 @@ def _alert_rules_error(self, event):

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

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -604,7 +604,9 @@ 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, # pyright: ignore
)

if expected_relation_role == RelationRole.provides:
Expand Down Expand Up @@ -866,20 +868,20 @@ def _from_dir(self, dir_path: Path, recursive: bool) -> List[dict]:

return alert_groups

def add_path(self, path: str, *, recursive: bool = False):
def add_path(self, path_str: str, *, recursive: bool = False):
"""Add rules from a dir path.
All rules from files are aggregated into a data structure representing a single rule file.
All group names are augmented with juju topology.
Args:
path: either a rules file or a dir of rules files.
path_str: either a rules file or a dir of rules files.
recursive: whether to read files recursively or not (no impact if `path` is a file).
Raises:
InvalidAlertRulePathError: if the provided path is invalid.
"""
path = Path(path) # type: Path
path = Path(path_str) # type: Path
if path.is_dir():
self.alert_groups.extend(self._from_dir(path, recursive))
elif path.is_file():
Expand Down Expand Up @@ -992,6 +994,8 @@ def __init__(self, handle, relation, relation_id, app=None, unit=None):

def snapshot(self) -> Dict:
"""Save event information."""
if not self.relation:
return {}
snapshot = {"relation_name": self.relation.name, "relation_id": self.relation.id}
if self.app:
snapshot["app_name"] = self.app.name
Expand Down Expand Up @@ -1052,7 +1056,7 @@ class LokiPushApiEvents(ObjectEvents):
class LokiPushApiProvider(Object):
"""A LokiPushApiProvider class."""

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

def __init__(
self,
Expand Down Expand Up @@ -1146,11 +1150,11 @@ def _on_logging_relation_changed(self, event: HookEvent):
event: a `CharmEvent` in response to which the consumer
charm must update its relation data.
"""
should_update = self._process_logging_relation_changed(event.relation)
should_update = self._process_logging_relation_changed(event.relation) # pyright: ignore
if should_update:
self.on.loki_push_api_alert_rules_changed.emit(
relation=event.relation,
relation_id=event.relation.id,
relation=event.relation, # pyright: ignore
relation_id=event.relation.id, # pyright: ignore
app=self._charm.app,
unit=self._charm.unit,
)
Expand Down Expand Up @@ -1517,7 +1521,7 @@ def loki_endpoints(self) -> List[dict]:
class LokiPushApiConsumer(ConsumerBase):
"""Loki Consumer class."""

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

def __init__(
self,
Expand Down Expand Up @@ -1760,7 +1764,7 @@ class LogProxyConsumer(ConsumerBase):
role.
"""

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

def __init__(
self,
Expand Down Expand Up @@ -1885,7 +1889,7 @@ def _on_relation_departed(self, _: RelationEvent) -> None:
self._container.stop(WORKLOAD_SERVICE_NAME)
self.on.log_proxy_endpoint_departed.emit()

def _get_container(self, container_name: str = "") -> Container:
def _get_container(self, container_name: str = "") -> Container: # pyright: ignore
"""Gets a single container by name or using the only container running in the Pod.
If there is more than one container in the Pod a `PromtailDigestError` is emitted.
Expand Down Expand Up @@ -1959,7 +1963,9 @@ def _add_pebble_layer(self, workload_binary_path: str) -> None:
}
},
}
self._container.add_layer(self._container_name, pebble_layer, combine=True)
self._container.add_layer(
self._container_name, pebble_layer, combine=True # pyright: ignore
)

def _create_directories(self) -> None:
"""Creates the directories for Promtail binary and config file."""
Expand Down Expand Up @@ -1996,7 +2002,11 @@ def _push_binary_to_workload(self, binary_path: str, workload_binary_path: str)
"""
with open(binary_path, "rb") as f:
self._container.push(
workload_binary_path, f, permissions=0o755, encoding=None, make_dirs=True
workload_binary_path,
f,
permissions=0o755,
encoding=None, # pyright: ignore
make_dirs=True,
)
logger.debug("The promtail binary file has been pushed to the workload container.")

Expand Down
16 changes: 5 additions & 11 deletions lib/charms/oathkeeper/v0/forward_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,7 @@ def some_event_function(self, event: AuthConfigChangedEvent):
from typing import Dict, List, Mapping, Optional

import jsonschema
from ops.charm import (
CharmBase,
RelationBrokenEvent,
RelationChangedEvent,
RelationCreatedEvent,
RelationDepartedEvent,
)
from ops.charm import CharmBase, RelationBrokenEvent, RelationChangedEvent, RelationCreatedEvent
from ops.framework import EventBase, EventSource, Handle, Object, ObjectEvents
from ops.model import Relation, TooManyRelatedAppsError

Expand All @@ -72,7 +66,7 @@ def some_event_function(self, event: AuthConfigChangedEvent):

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

RELATION_NAME = "forward-auth"
INTERFACE_NAME = "forward_auth"
Expand Down Expand Up @@ -505,7 +499,7 @@ def __init__(
events = self.charm.on[relation_name]
self.framework.observe(events.relation_created, self._on_relation_created_event)
self.framework.observe(events.relation_changed, self._on_relation_changed_event)
self.framework.observe(events.relation_departed, self._on_relation_departed_event)
self.framework.observe(events.relation_broken, self._on_relation_broken_event)

def _on_relation_created_event(self, event: RelationCreatedEvent) -> None:
"""Update the relation with provider data when a relation is created."""
Expand All @@ -525,8 +519,8 @@ def _on_relation_changed_event(self, event: RelationChangedEvent) -> None:
# Compare ingress-related apps with apps that requested the proxy
self._compare_apps()

def _on_relation_departed_event(self, event: RelationDepartedEvent) -> None:
"""Wipe the relation databag and notify the charm that the relation has departed."""
def _on_relation_broken_event(self, event: RelationBrokenEvent) -> None:
"""Wipe the relation databag and notify the charm that the relation is broken."""
# Workaround for https://github.com/canonical/operator/issues/888
self._pop_relation_data(event.relation.id)

Expand Down
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
10 changes: 5 additions & 5 deletions lib/charms/observability_libs/v1/kubernetes_service_patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def setUp(self, *unused):
from types import MethodType
from typing import List, Literal, Optional, Union

from lightkube import ApiError, Client
from lightkube import ApiError, Client # pyright: ignore
from lightkube.core import exceptions
from lightkube.models.core_v1 import ServicePort, ServiceSpec
from lightkube.models.meta_v1 import ObjectMeta
Expand All @@ -146,7 +146,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 = 7
LIBPATCH = 9

ServiceType = Literal["ClusterIP", "LoadBalancer"]

Expand Down Expand Up @@ -268,7 +268,7 @@ def _patch(self, _) -> None:
PatchFailed: if patching fails due to lack of permissions, or otherwise.
"""
try:
client = Client()
client = Client() # pyright: ignore
except exceptions.ConfigError as e:
logger.warning("Error creating k8s client: %s", e)
return
Expand Down Expand Up @@ -300,7 +300,7 @@ def is_patched(self) -> bool:
Returns:
bool: A boolean indicating if the service patch has been applied.
"""
client = Client()
client = Client() # pyright: ignore
return self._is_patched(client)

def _is_patched(self, client: Client) -> bool:
Expand All @@ -314,7 +314,7 @@ def _is_patched(self, client: Client) -> bool:
raise

# Construct a list of expected ports, should the patch be applied
expected_ports = [(p.port, p.targetPort) for p in self.service.spec.ports]
expected_ports = [(p.port, p.targetPort) for p in self.service.spec.ports] # type: ignore[attr-defined]
# Construct a list in the same manner, using the fetched service
fetched_ports = [
(p.port, p.targetPort) for p in service.spec.ports # type: ignore[attr-defined]
Expand Down
Loading

0 comments on commit 006d759

Please sign in to comment.