Skip to content

Commit 04affa3

Browse files
authored
Merge pull request #179 from dynatrace-oss/dev
Workaround invalid schema metric name regex pattern
2 parents b0bb03b + 8878f33 commit 04affa3

File tree

6 files changed

+69
-32
lines changed

6 files changed

+69
-32
lines changed

.bumpversion.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 1.6.19
2+
current_version = 1.6.21
33
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)
44
serialize =
55
{major}.{minor}.{patch}

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ extensions for Dynatrace Extension Framework 2.0.
66
<p>
77
<a href="https://pypi.org/project/dt-cli/"><img alt="PyPI" src="https://img.shields.io/pypi/v/dt-cli?color=blue&logo=python&logoColor=white"></a>
88
<a href="https://pypi.org/project/dt-cli/"><img alt="PyPI - Python Version" src="https://img.shields.io/pypi/pyversions/dt-cli?logo=python&logoColor=white"></a>
9-
<a href="https://github.com/dynatrace-oss/dt-cli/actions/workflows/built-test-release.yml"><img alt="GitHub Workflow Status (main branch)" src="https://img.shields.io/github/actions/workflow/status/dynatrace-oss/dt-cli/test.yml?branch=main&logo=github"></a>
9+
<a href="https://github.com/dynatrace-oss/dt-cli/actions/workflows/test.yml"><img alt="GitHub Workflow Status (main branch)" src="https://img.shields.io/github/actions/workflow/status/dynatrace-oss/dt-cli/test.yml?branch=main&logo=github"></a>
1010
</p>
1111

1212
## Features

dtcli/scripts/dt.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import re
2121
import sys
2222
from pathlib import Path
23+
from pprint import pprint
2324

2425
import click
2526
import requests # noqa:I201
@@ -838,16 +839,21 @@ def delete(**kwargs):
838839
)
839840
def validate_schema(instance, **kwargs):
840841
errors = _validate_schema.validate_schema(
841-
instance_object=instance, schema_entrypoint=kwargs["schema_entrypoint"],
842-
warn=functools.partial(click.echo, err=True))
842+
extension_yaml_path=instance, extension_schema_path=kwargs["schema_entrypoint"],
843+
warn=functools.partial(click.echo, err=True),
844+
)
843845
invalid = False
844846
if errors:
845847
invalid = True
846848
for i, e in enumerate(errors):
847849
print(f'{10 * "-"} error {i} {10 * "-"}', file=sys.stderr)
848850
print(f'line: {e["line"]}, column: {e["column"]}', file=sys.stderr)
849851
print(f'path: {e["path"]}', file=sys.stderr)
850-
print(f'cause: {e["cause"]}', file=sys.stderr)
852+
cause = e["cause"]
853+
if isinstance(cause, dict):
854+
pprint(f'cause: {cause}', stream=sys.stderr)
855+
else:
856+
print(f'cause: {e["cause"]}', file=sys.stderr)
851857
if invalid:
852858
print(f"{30 * '-'}", file=sys.stderr)
853859
raise click.ClickException(f"{i + 1} validation errors total, aborting!")

dtcli/validate_schema.py

+56-25
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import json
22
import pathlib
33
from pathlib import Path
4-
from typing import List, Union, Callable
4+
from typing import Any, List, Union, Callable
55

6-
import jsonschema
6+
from jsonschema import Draft202012Validator, Validator, ValidationError
7+
8+
from referencing import Registry, Resource
79

810
import yaml
911

@@ -36,37 +38,60 @@ def backtrack_yaml_location(path: List[Union[int, str]], ast: YamlAST) -> yaml.e
3638
assert 0, "unreachable switch branch"
3739

3840

39-
def validate_schema(instance_object: Path, schema_entrypoint: Path, warn: Callable[[str], None]) -> list:
40-
subschemas_path = pathlib.Path(schema_entrypoint).parent
41+
def remove_unsupported_regex_patterns(data: Any) -> dict:
42+
if isinstance(data, dict):
43+
cleanedup_dict = {
44+
k: remove_unsupported_regex_patterns(v) for k, v in data.items()
45+
# if not (k == "pattern" and isinstance(v, str) and r"\\p" in v)
46+
if not (k == "pattern" and isinstance(v, str) and r"\p" in v)
47+
}
48+
return cleanedup_dict
49+
elif isinstance(data, list):
50+
cleanedup_list = [
51+
remove_unsupported_regex_patterns(i) for i in data
52+
]
53+
return cleanedup_list
54+
else:
55+
return data
56+
57+
58+
def validate_schema(extension_yaml_path: Path, extension_schema_path: Path, warn: Callable[[str], None]) -> list:
59+
schema_dir_path = pathlib.Path(extension_schema_path).parent
4160

42-
with open(instance_object, "r") as yaml_in:
61+
with open(extension_yaml_path, "r") as yaml_in:
4362
instance = yaml.safe_load(yaml_in)
4463

45-
with open(schema_entrypoint) as f:
46-
s = json.load(f)
64+
with open(extension_schema_path) as f:
65+
schema_data = json.load(f)
66+
cleanedup_schema_data = remove_unsupported_regex_patterns(schema_data)
4767

48-
schema_store = {}
49-
for subschema_candidate in filter(lambda f: f.is_file, pathlib.Path(subschemas_path).iterdir()):
68+
subschema_paths = [
69+
p for p in schema_dir_path.iterdir() if p.is_file() and extension_schema_path.absolute() != p.absolute()
70+
]
71+
72+
resources: list[tuple[str, dict]] = []
73+
for c in subschema_paths:
5074
try:
51-
with open(subschema_candidate) as f:
52-
sub = json.load(f)
75+
with open(c) as f:
76+
subschema_data = json.load(f)
5377
except json.decoder.JSONDecodeError:
54-
warn(f"skipping subschema {subschema_candidate}, malformed json")
55-
# print(f"skipping subschema {subschema_candidate}, malformed json", file=sys.stderr)
78+
warn(f"skipping subschema {c}, malformed json")
5679
else:
57-
sub_id = sub["$id"]
58-
schema_store[sub_id] = sub
59-
60-
resolver = jsonschema.validators.RefResolver.from_schema(s, store=schema_store)
61-
62-
validator_cls = jsonschema.validators.validator_for(s)
63-
validator_cls.check_schema(s) # against META_SCHEMA
64-
validator = validator_cls(s, resolver=resolver)
65-
66-
with open(instance_object, "r") as f:
80+
cleanedup_subschema_data = remove_unsupported_regex_patterns(subschema_data)
81+
subschema_uri = cleanedup_subschema_data["$id"]
82+
subschema = Resource.from_contents(cleanedup_subschema_data)
83+
resources.append((subschema_uri, subschema))
84+
85+
registry = Registry().with_resources(resources)
86+
validator: Validator = Draft202012Validator(
87+
cleanedup_schema_data,
88+
registry=registry,
89+
)
90+
91+
with open(extension_yaml_path, "r") as f:
6792
file = yaml.compose(f)
6893

69-
def process_validation_error(error):
94+
def process_validation_error(error: ValidationError):
7095
err_loc = backtrack_yaml_location(error.absolute_path, file)
7196

7297
# TODO: add typo finder for some cases - like enum mismatch
@@ -77,4 +102,10 @@ def process_validation_error(error):
77102
"cause": error.message
78103
}
79104

80-
return list(map(process_validation_error, validator.iter_errors(instance)))
105+
detected_errors = list(validator.iter_errors(instance))
106+
errors_info: list[dict] = []
107+
for err in detected_errors:
108+
error_info = process_validation_error(err)
109+
errors_info.append(error_info)
110+
111+
return errors_info

dtcli/version.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
__version__ = "1.6.19"
15+
__version__ = "1.6.21"

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ packages = [
1212
]
1313
readme = "README.md"
1414
repository = "https://github.com/dynatrace-oss/dt-cli"
15-
version = "1.6.19"
15+
version = "1.6.21"
1616

1717
[tool.poetry.dependencies]
1818
PyYAML = "^6.0"

0 commit comments

Comments
 (0)