Skip to content

Commit

Permalink
test compatibility API with protopace
Browse files Browse the repository at this point in the history
  • Loading branch information
keejon committed Jul 16, 2024
1 parent 2148a61 commit 4f5815a
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 5 deletions.
11 changes: 9 additions & 2 deletions karapace/compatibility/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,17 @@ def check_jsonschema_compatibility(reader: Draft7Validator, writer: Draft7Valida
return jsonschema_compatibility(reader, writer)


def check_protobuf_compatibility(reader: ProtobufSchema, writer: ProtobufSchema) -> SchemaCompatibilityResult:
return check_protobuf_schema_compatibility(reader, writer)
def check_protobuf_compatibility(
reader: ProtobufSchema, writer: ProtobufSchema, use_protopace: bool = False
) -> SchemaCompatibilityResult:
return check_protobuf_schema_compatibility(reader, writer, use_protopace)


def check_compatibility(
old_schema: ParsedTypedSchema,
new_schema: ValidatedTypedSchema,
compatibility_mode: CompatibilityModes,
use_protopace: bool = False,
) -> SchemaCompatibilityResult:
"""Check that `old_schema` and `new_schema` are compatible under `compatibility_mode`."""
if compatibility_mode is CompatibilityModes.NONE:
Expand Down Expand Up @@ -148,23 +151,27 @@ def check_compatibility(
result = check_protobuf_compatibility(
reader=new_schema.schema,
writer=old_schema.schema,
use_protopace=use_protopace,
)
elif compatibility_mode in {CompatibilityModes.FORWARD, CompatibilityModes.FORWARD_TRANSITIVE}:
result = check_protobuf_compatibility(
reader=old_schema.schema,
writer=new_schema.schema,
use_protopace=use_protopace,
)

elif compatibility_mode in {CompatibilityModes.FULL, CompatibilityModes.FULL_TRANSITIVE}:
result = check_protobuf_compatibility(
reader=new_schema.schema,
writer=old_schema.schema,
use_protopace=use_protopace,
)
result = merge(
result,
check_protobuf_compatibility(
reader=old_schema.schema,
writer=new_schema.schema,
use_protopace=use_protopace,
),
)

Expand Down
26 changes: 24 additions & 2 deletions karapace/compatibility/protobuf/checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,34 @@
See LICENSE for details
"""
from avro.compatibility import SchemaCompatibilityResult, SchemaCompatibilityType
from karapace.protobuf.compare_result import CompareResult
from karapace.protobuf.compare_result import CompareResult, Modification
from karapace.protobuf.protopace import check_compatibility, IncompatibleError, Proto
from karapace.protobuf.schema import ProtobufSchema


def check_protobuf_schema_compatibility(reader: ProtobufSchema, writer: ProtobufSchema) -> SchemaCompatibilityResult:
def check_protobuf_schema_compatibility(
reader: ProtobufSchema, writer: ProtobufSchema, use_protopace: bool = False
) -> SchemaCompatibilityResult:
result = CompareResult()

if use_protopace:
old_deps = []
for _, val in reader.dependencies.items():
old_deps.append(Proto(val.name, val.get_schema().schema_str))
old_proto = Proto(reader.record_name, reader.to_schema(), old_deps)

new_deps = []
for _, val in writer.dependencies.items():
new_deps.append(Proto(val.name, val.get_schema().schema_str))
new_proto = Proto(writer.record_name, writer.to_schema(), old_deps)

try:
check_compatibility(new_proto, old_proto)
except IncompatibleError:
result.add_modification(Modification.PROTOPACE)

return result

writer.compare(reader, result)
if result.is_compatible():
return SchemaCompatibilityResult(SchemaCompatibilityType.compatible)
Expand Down
3 changes: 3 additions & 0 deletions karapace/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ class Config(TypedDict):
sentry: NotRequired[Mapping[str, object]]
tags: NotRequired[Mapping[str, object]]

use_protopace: bool


class ConfigDefaults(Config, total=False):
...
Expand Down Expand Up @@ -150,6 +152,7 @@ class ConfigDefaults(Config, total=False):
"name_strategy_validation": True,
"master_election_strategy": "lowest",
"protobuf_runtime_directory": "runtime",
"use_protopace": True,
}
SECRET_CONFIG_OPTIONS = [SASL_PLAIN_PASSWORD]

Expand Down
2 changes: 2 additions & 0 deletions karapace/protobuf/compare_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class Modification(Enum):
ONE_OF_FIELD_DROP = auto()
ONE_OF_FIELD_MOVE = auto()
FEW_FIELDS_CONVERTED_TO_ONE_OF = auto()
PROTOPACE = auto()

# protobuf compatibility issues is described in at
# https://yokota.blog/2021/08/26/understanding-protobuf-compatibility/
Expand All @@ -47,6 +48,7 @@ def is_compatible(self) -> bool:
self.FIELD_TAG_ALTER,
self.ONE_OF_FIELD_DROP,
self.FEW_FIELDS_CONVERTED_TO_ONE_OF,
self.PROTOPACE,
] # type: ignore[comparison-overlap]


Expand Down
2 changes: 1 addition & 1 deletion karapace/protobuf/protopace/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
See LICENSE for details
"""

from .protopace import check_compatibility, format_proto, Proto # noqa: F401
from .protopace import check_compatibility, format_proto, IncompatibleError, Proto # noqa: F401
1 change: 1 addition & 0 deletions karapace/schema_registry_apis.py
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,7 @@ async def compatibility_check(
old_schema=old_schema,
new_schema=new_schema,
compatibility_mode=compatibility_mode,
use_protopace=self.config["use_protopace"],
)
if is_incompatible(result):
self.r({"is_compatible": False}, content_type)
Expand Down

0 comments on commit 4f5815a

Please sign in to comment.