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

Is evaluating an object without knowing the proto definitions conceptually intended? #103

Closed
drx777 opened this issue Feb 4, 2020 · 3 comments

Comments

@drx777
Copy link

drx777 commented Feb 4, 2020

This may not be the best place to discuss this, but I wasn't quite sure where to put it otherwise.

We have a go service providing the CEL conformance functionality exposed via gRPC. We want to use it to evaluate expressions against arbitrary protobuf messages, about which the CEL service doesn't know anything about. Is this possible?

Even when I use a protobuf message that I know is known to the service (as it's part of its own API), I don't get the response I expect.

Here is a code snippet (complete code could be made available if that helps):

private static final ManagedChannel channel =
    ManagedChannelBuilder.forAddress("127.0.0.1", 10001).usePlaintext().directExecutor().build();
private static final ConformanceServiceBlockingStub stub =
    ConformanceServiceGrpc.newBlockingStub(channel);

// ...

var evaluationExpression = "status.message == \"test\"";

var parsed = stub.parse(ParseRequest.newBuilder().setCelSource(evaluationExpression).build());
var evalRequestBuilder = EvalRequest.newBuilder().setParsedExpr(parsed.getParsedExpr());

var sourcePosition = Status.newBuilder().setMessage("test").build();

var builder = ExprValue.newBuilder();
var typeUrl = "/google.rpc.Status";
builder.getValueBuilder().getObjectValueBuilder().setTypeUrl(typeUrl);
builder
    .getValueBuilder()
    .getObjectValueBuilder()
    .setValue(Any.pack(sourcePosition, typeUrl).toByteString());

evalRequestBuilder.putBindings("status", builder.build());
var request = evalRequestBuilder.build();
var evaluated = stub.eval(request);
System.out.println("result: " + evaluated);

And this is the result I get:

result: result {
  error {
    errors {
      code: 2
      message: "unknown type: \'google.rpc.Status\'"
    }
  }
}

If I use an unknown type, I get
io.grpc.StatusRuntimeException: UNKNOWN: can't convert binding status: any: message type "google.rpc.StatusNonExistingType" isn't linked in

I get the impression, that I'm missing some basic understanding and would appreciate any explanation and pointers towards understanding how this is supposed to work. Thank you!

@TristonianJones
Copy link
Collaborator

TristonianJones commented Feb 5, 2020

Hi David,

You are always welcome to reach out to cel-go-discuss@googlegroups.com, especially if there's some of the Go code involved.

The short answer to your question is that evaluation over protos which are not linked into the environment and added as cel.Types (or cel.TypeDescs) will result in an error. Generally the evaluation library is embedded in the binary where the evaluation occurs, but the parse / check can remain separate. For example, you could parse / check via gRPC, but evaluate the result with https://github.com/google/cel-cpp or https://github.com/google/cel-go.

However, you should be able build a JSON object in CEL with a top-level @type set to proper type url and get the protobuf.Any unpack methods to properly deserialize the JSON to a protobuf known to your environment.

Hope that helps,

-Tristan

@drx777
Copy link
Author

drx777 commented Feb 5, 2020

Thank you for your response and explanation. The problem is I'm in Java/Kotlin code here, so using the go library is not a possibility. I would have to make the protobuf definitions known to the CEL service, which somewhat defies the purpose of a general evaluation service. Still, thank you for the clarification.
Feel free to close the issue.

@TristonianJones
Copy link
Collaborator

TristonianJones commented Feb 5, 2020

Here are a few things to consider:

  • There is a chance we will open source a Java version of CEL.
  • The JSON trick I mentioned will make the object compatible with Any deserialization, and might work for you.
  • The conformance service was really only meant for handling a uniform set of test cases, and Go in particular doesn't support dynamic proto construction like some of the other proto implementations do. However, if you know the set of proto message types, you can modify the service and register the types in Go.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants