gRPC read method options before launching server - go

I'm currently trying to add scopes to secure my gRPC methods exposition and I'm using custom scopes for each methods.
Here is my scope class:
syntax = "proto3";
package grpc.proto.scopes;
import "google/protobuf/descriptor.proto";
extend google.protobuf.MethodOptions {
string scopes = 50000;
}
And I'm using it on my service scheme:
syntax = "proto3";
import "grpc/proto/scopes.proto";
package service;
service Service1 {
rpc Get(Request) returns (Response) {
option(grpc.proto.scopes.scopes) = "service1.feature.read";
}
rpc Post(Request) returns (Response) {
option(grpc.proto.scopes.scopes) = "service1.feature.write";
}
}
But my problem is the following:
server := grpc.NewServer([...my interceptor which uses my scopes...])
// <-- I must initialize my server with my interceptor but I need to have an access to the registry to retrieve scopes
proto.RegisterService1Server(server, s) // <-- Schemes are available on registry only on this line
I cannot initialize my scopes interceptor with proto shemes' scope because they are available only when they are registered on the server. But I can't initialize my server without my interceptor, so I'm blocked.
I can handle scope on the fly inside my interceptor with protoregistry.GlobalFiles.FindDescriptorByName but it will decrease performances.
Is there any way to get my shemes' scopes before initializing my server?

Related

Fabric8 customResourceDefinitions test

I am working on Fabric8 unit test, now I am trying to create a CRD against KubernetesServer.
import io.fabric8.kubernetes.api.model.apiextensions.v1.CustomResourceDefinition;
public class TestCertManagerService {
#Rule
public KubernetesServer server = new KubernetesServer();
#Test
#DisplayName("Should list all CronTab custom resources")
public void testCronTabCrd() throws IOException {
// Given
//server.expect().get().withPath("/apis/stable.example.com/v1/namespaces/default/crontabs").andReturn(HttpURLConnection.HTTP_OK, ?????).once();
KubernetesClient client = server.getClient();
CustomResourceDefinition cronTabCrd = client.apiextensions().v1().customResourceDefinitions()
.load(new BufferedInputStream(new FileInputStream("src/test/resources/crontab-crd.yml")))
.get();
client.apiextensions().v1().customResourceDefinitions().create(cronTabCrd);
}
}
When I ran it, I got the following error
TestCertManagerService > testCronTabCrd FAILED
io.fabric8.kubernetes.client.KubernetesClientException: Failure executing: GET at: https://localhost:60690/apis/apiextensions.k8s.io/v1/customresourcedefinitions.
at app//io.fabric8.kubernetes.client.dsl.base.OperationSupport.requestFailure(OperationSupport.java:694)
at app//io.fabric8.kubernetes.client.dsl.base.OperationSupport.requestFailure(OperationSupport.java:673)
at app//io.fabric8.kubernetes.client.dsl.base.OperationSupport.assertResponseCode(OperationSupport.java:626)
at app//io.fabric8.kubernetes.client.dsl.base.OperationSupport.handleResponse(OperationSupport.java:566)
at app//io.fabric8.kubernetes.client.dsl.base.OperationSupport.handleResponse(OperationSupport.java:527)
at app//io.fabric8.kubernetes.client.dsl.base.OperationSupport.handleResponse(OperationSupport.java:510)
at app//io.fabric8.kubernetes.client.dsl.base.BaseOperation.listRequestHelper(BaseOperation.java:136)
at app//io.fabric8.kubernetes.client.dsl.base.BaseOperation.list(BaseOperation.java:505)
at app//io.fabric8.kubernetes.client.dsl.base.BaseOperation.list(BaseOperation.java:494)
at app//io.fabric8.kubernetes.client.dsl.base.BaseOperation.list(BaseOperation.java:87)
at app//com.ibm.si.qradar.cp4s.service.certmanager.TestCertManagerService.testCronTabCrd(TestCertManagerService.java:94)
I have a few of questions:
(1) In this case, I am using v1() interface, sometimes I saw example code is using v1beta1(), what decides this version? By the way, I am using Kubernetes-client library 5.9.0
(2) In my code , I comments out this line
server.expect().get().withPath("/apis/stable.example.com/v1/namespaces/default/crontabs").andReturn(HttpURLConnection.HTTP_OK, ?????).once();
What is this statement for? In my case, I want to load a CRD, then create a CR, what is "?????" in the statement?
Any ideas for stack trace? How to fix it?
I appreciate it in advance.
From the code which you shared, it looks like you're using Fabric8 Kubernetes Mock Server in expectations mode. Expectations mode requires the user to set the REST API expectations. So the code shown below is setting some expectations from Mock Server viewpoint.
// Given
server.expect().get()
.withPath("/apis/stable.example.com/v1/namespaces/default/crontabs")
.andReturn(HttpURLConnection.HTTP_OK, getCronTabList())
.once();
These are the expectations set:
Mock Server would be requested a GET request at this URL: /apis/stable.example.com/v1/namespaces/default/crontabs . From URL we can expect a resource under stable.example.com apigroup with v1 version, default namespace and crontabs as plural.
When this URL is being hit, you're also defining response code and response body in andReturn() method. First argument is the response code (200 in this case) and second argument is the response body (a List object of CronTab which would be serialized and sent as response by mock server).
This request is only hit .once(), if KubernetesClient created by Mock Server requests this endpoint more than once; the test would fail. If you want to hit the endpoint more than once, you can use .times(..) method instead.
But in your test I see you're loading a CustomResourceDefinition from YAML and creating it which doesn't seem to match the expectations you set earlier. If you're writing a test about creating a CustomResourceDefinition, it should look like this:
#Test
#DisplayName("Should Create CronTab CRD")
void testCronTabCrd() throws IOException {
// Given
KubernetesClient client = server.getClient();
CustomResourceDefinition cronTabCrd = client.apiextensions().v1()
.customResourceDefinitions()
.load(new BufferedInputStream(new FileInputStream("src/test/resources/crontab-crd.yml")))
.get();
server.expect().post()
.withPath("/apis/apiextensions.k8s.io/v1/customresourcedefinitions")
.andReturn(HttpURLConnection.HTTP_OK, cronTabCrd)
.once();
// When
CustomResourceDefinition createdCronTabCrd = client.apiextensions().v1()
.customResourceDefinitions()
.create(cronTabCrd);
// Then
assertNotNull(createdCronTabCrd);
}
Bdw, if you don't like setting REST expectations. Fabric8 Kubernetes Mock Server also has a CRUD mode which mock real Kubernetes APIServer. You can enable it like this:
#Rule
public KubernetesServer server = new KubernetesServer(true, true);
then use it in test like this:
#Test
#DisplayName("Should Create CronTab CRD")
void testCronTabCrd() throws IOException {
// Given
KubernetesClient client = server.getClient();
CustomResourceDefinition cronTabCrd = client.apiextensions().v1()
.customResourceDefinitions()
.load(new BufferedInputStream(new FileInputStream("src/test/resources/crontab-crd.yml")))
.get();
// When
CustomResourceDefinition createdCronTabCrd = client.apiextensions().v1()
.customResourceDefinitions()
.create(cronTabCrd);
// Then
assertNotNull(createdCronTabCrd);
}
I added CustomResourceLoadAndCreateTest and CustomResourceLoadAndCreateCrudTest tests in my demo repository: https://github.com/r0haaaan/kubernetes-mockserver-demo

customization in protobuf java generated code

We have a use case where, we have many RPC defined in different-different .proto files , and we generate a java based grpc stub code by using google's protobuf-java & protoc-gen-grpc-java as gradle plugin.
The requirement is we want to generate a new Service which flips the request, response and add stream to new flipped rpc.
So for example :
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
to be converted to like
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
rpc SayHelloStreaming (stream HelloReply) returns (stream HelloRequest) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
In java generated code I should be having 2 services for each original service. We just want the final java generated code to be having 2 services, the parser may/may not update original .proto files.
Is this customization possible with current protoc ? Can we extend the plugin and write ours -> Can someone please give some pointers.
Your question is unclear to me.
Revising proto files is a fundamental requirement of gRPC.
The Java tutorial on https://grpc.io includes an example of adding a method to a service. In part, this is because adding|removing|updating methods|messages|fields is a common behavior.
NOTE To clarify nomenclature, in your example, you're proposing adding a method to an existing service (definition). If you consider the proto as defining an API, this represents a non-breaking change. See Versioning gRPC services for a good overview. Existing clients will continue to work (they are only aware of SayHello) while new clients will be aware of SayHelloStreaming too.

prisma-select issue for custom output path

I am getting the below error when I try to use
const select = new PrismaSelect(info).value;
[Nest] 65877 - 17/05/2021, 16:45:13 [ExceptionsHandler] Cannot find module '.prisma/client'
My PrismaClient is in a custom path rather than the default, as I am using a monorepo for multiple microservices.
generator client {
provider = "prisma-client-js"
binaryTargets = ["native", "darwin"]
output = "../src/.generated/prisma/client"
}
Is there a way to point PrismaSelect to the correct Client?
The solution was shared by the author of the package
Import custom instance of Prisma Client
import { Prisma } from '../../.generated/prisma/client';
Pass dmmf object to PrismaSelect constructor
const select = new PrismaSelect(info, { dmmf: [Prisma.dmmf] }).value;

Is there any postman like client for protobuffer

I want to develop a protocol-buffer type RESTful API that replaces JSON with protocol-buffer.
For example, a Spring Boot implement:
#RestController
#RequestMapping("account")
public class AccountController {
#RequestMapping(
path = "ListAccount",
method = RequestMethod.POST,
consumes = {"application/x-protobuf", "application/x-protobuf;charset=UTF-8"},
produces = {"application/x-protobuf", "application/x-protobuf;charset=UTF-8"})
public ListAccountResponse listAccount(ListAccountRequest request) {
// do something
ListAccountResponse response = ListAccountResponse.newBuilder().build();
return response;
}
}
syntax = "proto3";
option java_multiple_files = true;
option java_package = "account.proto.api";
package account.api;
import "common/pagination.proto";
import "common/valid.proto";
import "account/data/account.proto";
message ListAccountRequest {
common.Pagination page = 1 [(valid.validate) = true];
}
message ListAccountResponse {
repeated account.data.Account accounts = 1;
common.Pagination page = 2;
}
It seems that no a GUI client like postman for testing protocol-buffer API, which make me writing a tester in java. I will appreciate it if someone can tell me the answer.
You can use BloomRpc.First of all you should import your proto files and after that change format of request according to your rpc service.
you can use protoman A Postman-like API client for protobuf-based messages.
https://github.com/spluxx/Protoman

Serialization error in service stack when using client library

I have a ServiceStack REST service (PUT and POST) which I have tested with fiddler and if no errors are raised I return
new HttpResult(HttpStatusCode.OK);
Now I am testing the same REST service with the service stack client, I have:
var client = new XmlServiceClient("url"));
client.Post<ChangeServerLicenseDto>("", new ChangeServerLicenseDto()
{ServerName = model.ServerName});
and I get the exception on the REST service when I do
return new HttpResult(HttpStatusCode.OK)
and the error raised is :
500 (Error in line 1 position 76. Expecting element 'ChangeServerLicense'
from namespace ''.. Encountered 'Element' with name 'HttpStatusCode',
namespace 'http://schemas.datacontract.org/2004/07/System.Net'.)
My client code is in a MVC action method (POST).
My datacontract for the RestService is :
[DataContract(Name = "ChangeServerLicense", Namespace = "")]
[RestService("url", "POST", "application/xml")]
public class ChangeServerLicenseDto
{
[DataMember(Name = "ServerName", Order = 1)]
public string ServerName { get; set; }
}
The convention of signalling a successful response is to return an empty Response DTO (which by default returns a 200 OK). Also Send<TResponse>(...) does a POST so if you don't want to include the url in the request, use Send which will POST the request to the automatic pre-defined routes:
var client = new XmlServiceClient("url"));
client.Send<ChangeServerLicenseDtoResponse>(
new ChangeServerLicenseDto {ServerName = model.ServerName});
Otherwise if you still want to use .Post<T>(...) include the URL for the custom route where your services is mounted.
Note: I generally dislike using Dto suffixes on DTOs which are the most important API in your service - I explain in a bit more detail why here.

Resources