Skip to content

Commit

Permalink
Confirm changes to a config file produce different has values
Browse files Browse the repository at this point in the history
  • Loading branch information
addyess committed Aug 22, 2024
1 parent a97748f commit 5c7fe83
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 14 deletions.
22 changes: 12 additions & 10 deletions charms/kubernetes_snaps.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import os
import re
from base64 import b64encode
from functools import lru_cache
from pathlib import Path
from socket import getfqdn, gethostname
from subprocess import DEVNULL, CalledProcessError, call, check_call, check_output
Expand Down Expand Up @@ -479,17 +478,20 @@ def configure_scheduler(extra_args_config, kubeconfig):
)


@lru_cache
def _sha256_file(config_file):
def _sha256_file(config_file: str) -> hashlib.sha256:
h = hashlib.sha256()
if Path(config_file).exists():
with open(config_file, "rb") as file:
h.update(config_file.encode())
config_file = Path(config_file)
if config_file.exists():
with config_file.open("rb") as file:
while True:
# Reading is buffered, so we can read smaller chunks.
chunk = file.read(h.block_size)
if not chunk:
break
h.update(chunk)
else:
h.update(b"--empty--")
return h


Expand All @@ -505,7 +507,7 @@ def _dict_compare(d1, d2):


@contextlib.contextmanager
def _calculate_config_difference(service, args, config_files):
def _calculate_config_difference(service: str, args, config_files):
args_hash = _snap_common_path(service) / "args-hash.txt"

# gather existing config hash
Expand All @@ -524,18 +526,18 @@ def _calculate_config_difference(service, args, config_files):
# discern differences
added, removed, modified, _ = _dict_compare(updated, current)
for key in added:
log.debug("New config value %s in test", key)
log.debug("%s: Added config value %s", service.capitalize(), key)
for key in removed:
log.debug("Dropped config value %s in test", key)
log.debug("%s: Dropped config value %s", service.capitalize(), key)
for key in modified:
log.debug("Updated config value %s in test", key)
log.debug("%s: Updated config value %s", service.capitalize(), key)

different = added or removed or modified
yield different
if different:
yaml.safe_dump(updated, args_hash.open("w"))
else:
log.debug("No config changes detected for %s", service)
log.debug("%s: No config changes detected", service.capitalize())


def configure_kubernetes_service(
Expand Down
33 changes: 29 additions & 4 deletions tests/unit/test_kubernetes_snaps.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ def test_configure_apiserver(mock_path, configure_kubernetes_service, external_c
@mock.patch("charms.kubernetes_snaps.service_restart")
def test_configure_kubernetes_service_same_config(service_restart, check_call, caplog):
caplog.set_level(logging.DEBUG)
log_message = "No config changes detected for test"
log_message = "Test: No config changes detected"
base_args = {"arg1": "val1", "arg2": "val2"}
extra_args = "arg2=val2-updated arg3=val3"
hashed = {
Expand All @@ -272,14 +272,14 @@ def test_configure_kubernetes_service_same_config(service_restart, check_call, c
@pytest.mark.parametrize(
"extra_args, log_message",
[
("arg2=val2-updated", "Dropped config value arg3 in test"),
("arg2=val2-updated", "Test: Dropped config value arg3"),
(
"arg2=val2-updated arg3=val3 arg4=val4",
"New config value arg4 in test",
"Test: Added config value arg4",
),
(
"arg2=val2-updated arg3=val3-updated",
"Updated config value arg3 in test",
"Test: Updated config value arg3",
),
],
ids=["drop_key", "add_key", "update_key"],
Expand All @@ -305,3 +305,28 @@ def test_configure_kubernetes_service_difference(
mock_open.assert_has_calls([mock.call(), mock.call("w")], any_order=True)
safe_dump.assert_called_once()
assert log_message in caplog.text


@mock.patch("pathlib.Path.exists")
def test_sha256_file(mock_exists):
# Non Existent file
mock_exists.return_value = False
hash = kubernetes_snaps._sha256_file("/path/to/file/1").hexdigest()
assert hash == "8054b8176bf428f030f0fb8b62ca2c26cf0b983196cfe97358cfb1e206aa9d75"

# Non Existent file with a different name
mock_exists.return_value = False
hash = kubernetes_snaps._sha256_file("/path/to/file/2").hexdigest()
assert hash == "f337cf841ac045041455bff9cc3f2e0b8a2a5bf5dfe44a0152be04e4fc2355b5"

# Existing file with same name but empty
mock_exists.return_value = True
with mock.patch("pathlib.Path.open", mock.mock_open(read_data=b"")):
hash = kubernetes_snaps._sha256_file("/path/to/file/2").hexdigest()
assert hash == "8d6fb329915afba8724a741f422894e127217854fe1934679e50d2115c2c3ca6"

# Existing file with same name with data
mock_exists.return_value = True
with mock.patch("pathlib.Path.open", mock.mock_open(read_data=b"data")):
hash = kubernetes_snaps._sha256_file("/path/to/file/2").hexdigest()
assert hash == "63699fd3e47d9eb242fe6763bc387a9f3f6d1ae3f08bf7a7c437cec51ce2d0c4"

0 comments on commit 5c7fe83

Please sign in to comment.