Skip to content

Commit

Permalink
[Refactoring] initial round: v0 (#23) (#24)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mehdi-Bendriss authored Jan 10, 2023
1 parent cc985cf commit 3304eb0
Show file tree
Hide file tree
Showing 16 changed files with 1,198 additions and 758 deletions.
23 changes: 23 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[report]
exclude_lines =
# Skip any pass lines such as may be used for @abstractmethod
pass

# Ignore abstract methods
@abstractmethod
@abc.abstractmethod

# Have to re-enable the standard pragma
pragma: no cover

# Don't complain about missing debug-only code:
def __repr__
if self\.debug

# Don't complain if tests don't hit defensive assertion code:
raise AssertionError
raise NotImplementedError

# Don't complain if non-runnable code isn't run:
if 0:
if __name__ == .__main__.:
57 changes: 57 additions & 0 deletions lib/charms/opensearch/v0/helper_charm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Copyright 2022 Canonical Ltd.
# See LICENSE file for licensing details.

"""Utility functions for charms related operations."""
import re

from charms.opensearch.v0.helper_enums import BaseStrEnum
from ops.model import ActiveStatus

# The unique Charmhub library identifier, never change it
LIBID = "293db55a2d8949f8aa5906d04cd541ba"

# Increment this major API version when introducing breaking changes
LIBAPI = 0

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


class Status:
"""Class for managing the various status changes in a charm."""

class CheckPattern(BaseStrEnum):
"""Enum for types of status comparison."""

Equal = "equal"
Start = "start"
End = "end"
Contain = "contain"
Interpolated = "interpolated"

def __init__(self, charm):
self.charm = charm

def clear(self, status_message: str, pattern: CheckPattern = CheckPattern.Equal):
"""Resets the unit status if it was previously blocked/maintenance with message."""
unit = self.charm.unit

condition: bool
match pattern:
case Status.CheckPattern.Equal:
condition = unit.status.message == status_message
case Status.CheckPattern.Start:
condition = unit.status.message.startswith(status_message)
case Status.CheckPattern.End:
condition = unit.status.message.endswith(status_message)
case Status.CheckPattern.Interpolated:
condition = (
re.fullmatch(status_message.replace("{}", "(?s:.*?)"), status_message)
is not None
)
case _:
condition = status_message in unit.status.message

if condition:
unit.status = ActiveStatus()
2 changes: 1 addition & 1 deletion lib/charms/opensearch/v0/helper_cluster.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Copyright 2022 Canonical Ltd.
# See LICENSE file for licensing details.

"""Utility class for getting cluster info, configuration info and suggestions."""
"""Utility classes and methods for getting cluster info, configuration info and suggestions."""

from typing import Dict, List

Expand Down
127 changes: 112 additions & 15 deletions lib/charms/opensearch/v0/helper_conf_setter.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
import re
import sys
import uuid
from abc import ABC, abstractmethod
from collections.abc import Mapping
from enum import Enum
from io import StringIO
from os.path import exists
from typing import Dict, List

from overrides import override
from ruamel.yaml import YAML, CommentedSeq
from ruamel.yaml.comments import CommentedSet

Expand Down Expand Up @@ -42,10 +44,11 @@ def __str__(self):
return self.value


class YamlConfigSetter:
"""Utility class for updating YAML config, supporting diverse object types and nestedness.
class ConfigSetter(ABC):
"""Base class for manipulating YAML Config, of multiple types and any depth level.
conf_setter = YamlConfigSetter() or another config setter
conf_setter = YamlConfigSetter()
put("file.yml", "a.b", "new_name")
put("file.yml", "a.b/c.obj/key3/key1.a/obj", {"a": "new_name_1", "b": ["hello", "world"]})
put("file.yml", "a.b/c.arr.simple/[0]", "hello")
Expand All @@ -57,9 +60,111 @@ class YamlConfigSetter:

def __init__(self, base_path: str = None):
"""base_path: if set, where to look for files relatively on "load/put/delete" methods."""
self.yaml = YAML()
self.base_path = self.__clean_base_path(base_path)

@abstractmethod
def load(self, config_file: str) -> Dict[str, any]:
"""Load the content of a YAML file."""
pass

@abstractmethod
def put(
self,
config_file: str,
key_path: str,
val: any,
sep="/",
output_type: OutputType = OutputType.file,
inline_array: bool = False,
output_file: str = None,
) -> Dict[str, any]:
"""Add or update the value of a key (or content of array at index / key) if it exists.
Args:
config_file (str): Path to the source config file
key_path (str): The path of the YAML key to target
val (any): The value to store for the passed key
sep (str): The separator / delimiter character to use in the key_path
output_type (OutputType): The type of output we're expecting from this operation,
i.e, set OutputType.all to have the output on both the console and target file
inline_array (bool): whether the operation should format arrays in:
- multiline fashion (false)
- between brackets (true)
output_file: Target file for the result config, by default same as config_file
Returns:
Dict[str, any]: The final version of the YAML config.
"""
pass

@abstractmethod
def delete(
self,
config_file: str,
key_path: str,
sep="/",
output_type: OutputType = OutputType.file,
output_file: str = None,
) -> Dict[str, any]:
"""Delete the value of a key (or content of array at index / key) if it exists.
Args:
config_file (str): Path to the source config file
key_path (str): The path of the YAML key to target
sep (str): The separator / delimiter character to use in the key_path
output_type (OutputType): The type of output we're expecting from this operation,
i.e, set OutputType.all to have the output on both the console and target file
output_file: Target file for the result config, by default same as config_file
Returns:
Dict[str, any]: The final version of the YAML config.
"""
pass

@abstractmethod
def replace(
self,
config_file: str,
old_val: str,
new_val: any,
regex: bool = False,
output_type: OutputType = OutputType.file,
output_file: str = None,
) -> None:
"""Replace any substring in a text file.
Args:
config_file (str): Path to the source config file
old_val (str): The value we wish to replace
new_val (any): The new value to replace old_val
regex (bool): Whether to treat old_val as a regex.
output_type (OutputType): The type of output we're expecting from this operation,
i.e, set OutputType.all to have the output on both the console and target file
output_file: Target file for the result config, by default same as config_file
"""
pass

@staticmethod
def __clean_base_path(base_path: str):
if base_path is None:
return ""

base_path = base_path.strip()
if not base_path.endswith("/"):
base_path = f"{base_path}/"

return base_path


class YamlConfigSetter(ConfigSetter):
"""Class for updating YAML config on the file system."""

def __init__(self, base_path: str = None):
"""base_path: if set, where to look for files relatively on "load/put/delete" methods."""
super().__init__(base_path)
self.yaml = YAML()

@override
def load(self, config_file: str) -> Dict[str, any]:
"""Load the content of a YAML file."""
path = f"{self.base_path}{config_file}"
Expand All @@ -78,6 +183,7 @@ def load(self, config_file: str) -> Dict[str, any]:

return data

@override
def put(
self,
config_file: str,
Expand All @@ -104,6 +210,7 @@ def put(

return data

@override
def delete(
self,
config_file: str,
Expand All @@ -125,6 +232,7 @@ def delete(

return data

@override
def replace(
self,
config_file: str,
Expand Down Expand Up @@ -315,14 +423,3 @@ def __flow_style() -> CommentedSeq:
ret = CommentedSeq()
ret.fa.set_flow_style()
return ret

@staticmethod
def __clean_base_path(base_path: str):
if base_path is None:
return ""

base_path = base_path.strip()
if not base_path.endswith("/"):
base_path = f"{base_path}/"

return base_path
Loading

0 comments on commit 3304eb0

Please sign in to comment.