Skip to content

Commit

Permalink
chore: update charm libraries
Browse files Browse the repository at this point in the history
  • Loading branch information
observability-noctua-bot committed Dec 16, 2024
1 parent 5b805c3 commit 9f549c7
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ def _on_certificate_removed(self, event: CertificateRemovedEvent):
from typing import List, Mapping

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

Expand All @@ -112,7 +113,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 = 8
LIBPATCH = 9

PYDEPS = ["jsonschema"]

Expand Down Expand Up @@ -391,3 +392,11 @@ def _on_relation_broken(self, event: RelationBrokenEvent) -> None:
None
"""
self.on.certificate_removed.emit(relation_id=event.relation.id)

def is_ready(self, relation: Relation) -> bool:
"""Check if the relation is ready by checking that it has valid relation data."""
relation_data = _load_relation_data(relation.data[relation.app])
if not self._relation_data_is_valid(relation_data):
logger.warning("Provider relation data did not pass JSON Schema validation: ")
return False
return True
45 changes: 37 additions & 8 deletions lib/charms/operator_libs_linux/v2/snap.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
import socket
import subprocess
import sys
import time
import urllib.error
import urllib.parse
import urllib.request
Expand All @@ -83,7 +84,7 @@

# 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


# Regex to locate 7-bit C1 ANSI sequences
Expand Down Expand Up @@ -332,19 +333,17 @@ def get(self, key: Optional[str], *, typed: bool = False) -> Any:

return self._snap("get", [key]).strip()

def set(self, config: Dict[str, Any], *, typed: bool = False) -> str:
def set(self, config: Dict[str, Any], *, typed: bool = False) -> None:
"""Set a snap configuration value.
Args:
config: a dictionary containing keys and values specifying the config to set.
typed: set to True to convert all values in the config into typed values while
configuring the snap (set with typed=True). Default is not to convert.
"""
if typed:
kv = [f"{key}={json.dumps(val)}" for key, val in config.items()]
return self._snap("set", ["-t"] + kv)

return self._snap("set", [f"{key}={val}" for key, val in config.items()])
if not typed:
config = {k: str(v) for k, v in config.items()}
self._snap_client._put_snap_conf(self._name, config)

def unset(self, key) -> str:
"""Unset a snap configuration value.
Expand Down Expand Up @@ -770,7 +769,33 @@ def _request(
headers["Content-Type"] = "application/json"

response = self._request_raw(method, path, query, headers, data)
return json.loads(response.read().decode())["result"]
response = json.loads(response.read().decode())
if response["type"] == "async":
return self._wait(response["change"])
return response["result"]

def _wait(self, change_id: str, timeout=300) -> JSONType:
"""Wait for an async change to complete.
The poll time is 100 milliseconds, the same as in snap clients.
"""
deadline = time.time() + timeout
while True:
if time.time() > deadline:
raise TimeoutError(f"timeout waiting for snap change {change_id}")
response = self._request("GET", f"changes/{change_id}")
status = response["status"]
if status == "Done":
return response.get("data")
if status == "Doing" or status == "Do":
time.sleep(0.1)
continue
if status == "Wait":
logger.warning("snap change %s succeeded with status 'Wait'", change_id)
return response.get("data")
raise SnapError(
f"snap change {response.get('kind')!r} id {change_id} failed with status {status}"
)

def _request_raw(
self,
Expand Down Expand Up @@ -818,6 +843,10 @@ def get_installed_snap_apps(self, name: str) -> List:
"""Query the snap server for apps belonging to a named, currently installed snap."""
return self._request("GET", "apps", {"names": name, "select": "service"})

def _put_snap_conf(self, name: str, conf: Dict[str, Any]):
"""Set the configuration details for an installed snap."""
return self._request("PUT", f"snaps/{name}/conf", body=conf)


class SnapCache(Mapping):
"""An abstraction to represent installed/available packages.
Expand Down

0 comments on commit 9f549c7

Please sign in to comment.