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

fix: add checks and log_targets to ops.testing #1268

Merged
merged 23 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
50f82b4
Add checks to ops.testing
amandahla Jun 21, 2024
f695cce
Merge remote-tracking branch 'origin' into iss1112
amandahla Jun 26, 2024
8943ddf
Add log_targets to ops.testing
amandahla Jun 26, 2024
82613de
Update ops/pebble.py
amandahla Jun 28, 2024
1049429
Merge remote-tracking branch 'upstream/main' into iss1112
amandahla Jun 28, 2024
3832876
Fix merges and change layer to test more checks
amandahla Jun 28, 2024
8ec63df
Add blank line before each for in testing
amandahla Jun 28, 2024
4e961e9
Replace value on for value for in check and log target
amandahla Jun 28, 2024
04ebb94
Remove comma e intermediate pebble plan check in test
amandahla Jun 28, 2024
67da365
Improve test by checking environment too
amandahla Jun 28, 2024
9bdf756
Change labels from optional to non-optional dict
amandahla Jun 28, 2024
2907ee6
Ignore static errors for update
amandahla Jun 28, 2024
b60e2b5
Update test/test_testing.py
amandahla Jul 1, 2024
8c74179
Update test/test_testing.py
amandahla Jul 1, 2024
c261bd8
Update test/test_testing.py
amandahla Jul 1, 2024
e11d8b7
Remove commas
amandahla Jul 1, 2024
0173d19
Update ops/testing.py
amandahla Jul 2, 2024
0eebc22
Update test/test_testing.py
amandahla Jul 2, 2024
d3f2a9a
Update test/test_testing.py
amandahla Jul 2, 2024
86e6f7f
chore: bump version for the coming month's work (#1277)
tonyandrewmeyer Jul 2, 2024
0d8bf02
Change from lt to layer_target
amandahla Jul 2, 2024
2659a33
Merge branch 'main' into iss1112
benhoyt Jul 2, 2024
0a7a73f
Make style consistent between services, checks, and log_targets
benhoyt Jul 2, 2024
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
88 changes: 85 additions & 3 deletions ops/pebble.py
Original file line number Diff line number Diff line change
Expand Up @@ -1135,6 +1135,73 @@ def __eq__(self, other: Union['CheckDict', 'Check']) -> bool:
else:
return NotImplemented

def _merge_exec(self, other: 'ExecDict') -> None:
"""Merges this exec object with another exec definition.

For attributes present in both objects, the passed in exec
attributes take precedence.
"""
if self.exec is None:
self.exec = {}
for name, value in other.items():
if not value:
continue
if name == 'environment':
current = self.exec.get(name, {})
current.update(value) # type: ignore
self.exec[name] = current
else:
self.exec[name] = value

def _merge_http(self, other: 'HttpDict') -> None:
"""Merges this http object with another http definition.

For attributes present in both objects, the passed in http
attributes take precedence.
"""
if self.http is None:
self.http = {}
for name, value in other.items():
if not value:
continue
if name == 'headers':
current = self.http.get(name, {})
current.update(value) # type: ignore
self.http[name] = current
else:
self.http[name] = value

def _merge_tcp(self, other: 'TcpDict') -> None:
"""Merges this tcp object with another tcp definition.

For attributes present in both objects, the passed in tcp
attributes take precedence.
"""
if self.tcp is None:
self.tcp = {}
for name, value in other.items():
if not value:
continue
self.tcp[name] = value

def _merge(self, other: 'Check'):
"""Merges this check object with another check definition.

For attributes present in both objects, the passed in check
attributes take precedence.
"""
for name, value in other.__dict__.items():
if not value or name == 'name':
continue
if name == 'http':
self._merge_http(value)
elif name == 'tcp':
self._merge_tcp(value)
elif name == 'exec':
self._merge_exec(value)
else:
benhoyt marked this conversation as resolved.
Show resolved Hide resolved
setattr(self, name, value)


class CheckLevel(enum.Enum):
"""Enum of check levels."""
Expand Down Expand Up @@ -1162,9 +1229,8 @@ def __init__(self, name: str, raw: Optional['LogTargetDict'] = None):
self.location = dct.get('location', '')
self.services: List[str] = list(dct.get('services', []))
labels = dct.get('labels')
if labels is not None:
labels = copy.deepcopy(labels)
self.labels: Optional[Dict[str, str]] = labels
labels = copy.deepcopy(labels) if labels is not None else {}
self.labels: Dict[str, str] = labels

def to_dict(self) -> 'LogTargetDict':
"""Convert this log target object to its dict representation."""
Expand All @@ -1189,6 +1255,22 @@ def __eq__(self, other: Union['LogTargetDict', 'LogTarget']):
else:
return NotImplemented

def _merge(self, other: 'LogTarget'):
"""Merges this log target object with another log target definition.

For attributes present in both objects, the passed in log target
attributes take precedence.
"""
for name, value in other.__dict__.items():
if not value or name == 'name':
continue
if name == 'labels':
getattr(self, name).update(value)
amandahla marked this conversation as resolved.
Show resolved Hide resolved
elif name == 'services':
getattr(self, name).extend(value)
else:
setattr(self, name, value)


class FileType(enum.Enum):
"""Enum of file types."""
Expand Down
41 changes: 41 additions & 0 deletions ops/testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -3183,6 +3183,7 @@ def add_layer(
if not combine:
raise RuntimeError(f'400 Bad Request: layer "{label}" already exists')
layer = self._layers[label]

for name, service in layer_obj.services.items():
# 'override' is actually single quoted in the real error, but
# it shouldn't be, hopefully that gets cleaned up.
Expand All @@ -3205,6 +3206,46 @@ def add_layer(
else:
layer.services[name] = service

for name, check in layer_obj.checks.items():
amandahla marked this conversation as resolved.
Show resolved Hide resolved
if not check.override:
raise RuntimeError(
f'500 Internal Server Error: layer "{label}" must define'
f'"override" for check "{name}"'
)
if check.override not in ('merge', 'replace'):
raise RuntimeError(
f'500 Internal Server Error: layer "{label}" has invalid '
f'"override" value for check "{name}"'
)
elif check.override == 'replace':
layer.checks[name] = check
elif check.override == 'merge':
if combine and name in layer.checks:
c = layer.checks[name]
c._merge(check)
amandahla marked this conversation as resolved.
Show resolved Hide resolved
else:
layer.checks[name] = check

for name, log_target in layer_obj.log_targets.items():
if not log_target.override:
raise RuntimeError(
f'500 Internal Server Error: layer "{label}" must define'
f'"override" for log target "{name}"'
)
if log_target.override not in ('merge', 'replace'):
raise RuntimeError(
f'500 Internal Server Error: layer "{label}" has invalid '
f'"override" value for log target "{name}"'
)
elif log_target.override == 'replace':
layer.log_targets[name] = log_target
elif log_target.override == 'merge':
if combine and name in layer.log_targets:
lt = layer.log_targets[name]
lt._merge(log_target)
amandahla marked this conversation as resolved.
Show resolved Hide resolved
else:
layer.log_targets[name] = log_target

else:
self._layers[label] = layer_obj

Expand Down
2 changes: 1 addition & 1 deletion test/test_pebble.py
Original file line number Diff line number Diff line change
Expand Up @@ -1150,7 +1150,7 @@ def _assert_empty(self, target: pebble.LogTarget, name: str):
assert target.type == ''
assert target.location == ''
assert target.services == []
assert target.labels is None
assert target.labels == {}

def test_name_only(self):
target = pebble.LogTarget('tgt')
Expand Down
Loading
Loading