json: Add protobuf wrapper for streamer - #47088
Conversation
Signed-off-by: Filip Cacky <filip.cacky@cdn77.com>
Signed-off-by: Filip Cacky <filip.cacky@cdn77.com>
Signed-off-by: Filip Cacky <filip.cacky@cdn77.com>
Signed-off-by: Filip Cacky <filip.cacky@cdn77.com>
Signed-off-by: Filip Cacky <filip.cacky@cdn77.com>
Signed-off-by: Filip Cacky <filip.cacky@cdn77.com>
Signed-off-by: Filip Cacky <filip.cacky@cdn77.com>
af237aa to
dd25caa
Compare
|
Added Added Added examples for all types to config and cleaned up the redactions a bit, since they were all over the place. I'm thinking the redactions should probably copy over Redact test cases from cc @jmarantz |
Signed-off-by: Filip Cacky <filip.cacky@cdn77.com>
jmarantz
left a comment
There was a problem hiding this comment.
This looks great! Mostly minor nits and requests for more comments.
/wait
| public: | ||
| struct Options { | ||
| // Whether to emit a leading @type naming the message. | ||
| bool emit_type_url = false; |
There was a problem hiding this comment.
Not putting the "_" suffix on struct member variables is consistent with the Google style guide.
However the Envoy style guide calls this out as an explicit deviation: https://github.com/envoyproxy/envoy/blob/main/STYLE.md#deviations-from-google-c-style-guidelines
There was a problem hiding this comment.
I raised #47030 few days ago specifically because of this :D Apparently both styles are acceptable. I dislike the suffix on public interfaces, but I'll fix. I suppose its better than complaining about it in an issue and then doing the same x)
There was a problem hiding this comment.
It's reasonable to object to the style guide. I happen to agree with you stylistically.
However that discussion should be in the form of a PR to change the style guide, without other functional changes :)
| // Whether the keys are the proto field names or the lowerCamelCase ProtoJSON defaults to. | ||
| // https://protobuf.dev/programming-guides/json/#field-names | ||
| bool preserve_proto_field_names = false; | ||
| // Whether the fields the API marks sensitive are emitted, or replaced the way |
There was a problem hiding this comment.
optional nit: add blank link betweeen option member variables and their doc.
| bool ancestor_is_sensitive); | ||
|
|
||
| // Emits the redacted form of `field`'s value, a replacement for text and the type's default for | ||
| // anything else. Messages are handled by walking them, not redacting as whole. |
There was a problem hiding this comment.
I think I understand, but maybe it's worthwhile expanding on this a little.
e.g.
Leaf messages that are redacted are handled directly here. Messages with hiearchy (repeated fields and maps) are recursed fully, and the redactions occur only at leaves.
Is that right?
| bool field_is_sensitive_{false}; | ||
| }; | ||
|
|
||
| void nextElement(Frame& frame); |
There was a problem hiding this comment.
Add brief doc for nextElement. I think for nextElement and startField I'd like to know from looking at this header if it's also managing a stack owned by 'this'. Maybe call that out?
I assume it is, otherwise nextElement would be 'const'.
Note that these are both non-const methods and they take a mutable Frame objects. Can you just dive into the semantics a little more?
There was a problem hiding this comment.
Added comment and renamed to emitNextElement/emitNextField, also realized that next_field_ was interpreted as "current field" during nextElement, so i cleaned that up a bit too.
Both are entry points to emit Something, which may push on the stack, emitNextElement just handles repeated fields and maps.
| BufferStreamer::Level& level); | ||
|
|
||
| // Emits one value of `field`, or pushes a frame for it. `index` is which element of a repeated | ||
| // field to emit, or -1 for a field that is not repeated. |
There was a problem hiding this comment.
WDYT of making a named constant for -1 here?
There was a problem hiding this comment.
Changed to std::optional, emitValue then doesn't need the same comment about the sentinel and IMO looks nicer.
| field.type() != Field::TYPE_BYTES; | ||
| } | ||
|
|
||
| ProtobufTypes::MessagePtr redactedCopy(const Protobuf::Message& message, |
There was a problem hiding this comment.
do we need to copy the entire message to redact a field from it?
Couldn't we just stream out the message and redact at the leaf level?
Maybe this is because we have MessageUtil::redactAll we don't want to mess with, or maybe you have already gotten to the leaf level by the time this is called, in which case you can add comments :)
There was a problem hiding this comment.
Added a comment.
Everything is redacted leaf by leaf while streaming except some well-known types (the TODO message) and TypedStructs, which need to be reified via the type_url, so they go through MessageUtil::redact.
| @@ -0,0 +1,311 @@ | |||
| #include "source/common/buffer/buffer_impl.h" | |||
There was a problem hiding this comment.
how is the coverage looking for this test?
There was a problem hiding this comment.
96.4 %, added a test.
There was a problem hiding this comment.
What's missing? This is a whole bunch of new code, replacing complex old code, which is going to be hard to hand-validate so we are utterly reliant on unit tests covering every corner.
Come to think of it, for validation purposes, can you do differential fuzzing with protobuf's protojson generator?
There was a problem hiding this comment.
At this point just the early return for next() if stack_ is empty, which IIRC was needed for the streamed request.
Fuzzing as in generating random configurations? Probably yes although I've no idea how yet. I did run every /config_dump test side by side in the other PR, should also do the same with MessageUtil::redact.
|
For ensuring semantic coverage of the xDS data model I'd recommend @htuch and @adisuissa take a look at the proto streamer. |
Signed-off-by: Filip Cacky <filip.cacky@cdn77.com>
…ed fields instead of -1 sentinel Signed-off-by: Filip Cacky <filip.cacky@cdn77.com>
Signed-off-by: Filip Cacky <filip.cacky@cdn77.com>
Signed-off-by: Filip Cacky <filip.cacky@cdn77.com>
Signed-off-by: Filip Cacky <filip.cacky@cdn77.com>
Signed-off-by: Filip Cacky <filip.cacky@cdn77.com>
|
/retest |
Challenging to say if the same semantic coverage is acheived by both the proto-streamer and the current proto dumper. I don't see any red-flags, and assuming that there are enough tests covering different edge cases (specifically redacted fields), then it may be ok. High-level comment: please add a tracking issue that has the results (that were published in #46911), and add the issue to the PR description. |
Signed-off-by: Filip Cacky <filip.cacky@cdn77.com>
Commit Message: json: Add protobuf wrapper for streamer
Additional Description:
Adds Envoy::Json::MessageStreamer, which wraps a BufferStreamer::Level and serializes a Protobuf::Message by walking it with reflection.
The MessageStreamer supports redacting fields annotated with [(udpa.annotations.sensitive) = true] with the same output format as MessageUtil::redact.
Risk Level: Low
Testing: Added unit tests
Docs Changes: N/A
Release Notes: N/A
Platform Specific Features: N/A
[Optional Runtime guard:]
[Optional Fixes #Issue]
[Optional Fixes commit #PR or SHA]
[Optional Deprecated:]
[Optional API Considerations:]