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

Implementing graphql apis for label application rules #108

Merged
merged 16 commits into from
Nov 5, 2021
Merged
1 change: 1 addition & 0 deletions hypertrace-graphql-impl/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ dependencies {
implementation(project(":hypertrace-graphql-entity-type"))
implementation(project(":hypertrace-graphql-spaces-schema"))
implementation(project(":hypertrace-graphql-labels-schema"))
implementation(project(":hypertrace-graphql-label-application-rules-schema"))

implementation("org.slf4j:slf4j-api")
implementation("com.google.inject:guice")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.hypertrace.graphql.explorer.ExplorerSchemaModule;
import org.hypertrace.graphql.explorer.context.HypertraceExplorerContextModule;
import org.hypertrace.graphql.label.LabelSchemaModule;
import org.hypertrace.graphql.label.application.rules.LabelApplicationRuleSchemaModule;
import org.hypertrace.graphql.metric.MetricModule;
import org.hypertrace.graphql.spaces.SpacesSchemaModule;
import org.hypertrace.graphql.utils.metrics.gateway.GatewayMetricUtilsModule;
Expand Down Expand Up @@ -73,5 +74,6 @@ protected void configure() {
install(new SpacesSchemaModule());
install(new RequestTransformationModule());
install(new LabelSchemaModule());
install(new LabelApplicationRuleSchemaModule());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
plugins {
`java-library`
jacoco
id("org.hypertrace.jacoco-report-plugin")
}

dependencies {
api("com.google.inject:guice")
api("com.graphql-java:graphql-java")
api("org.hypertrace.core.graphql:hypertrace-core-graphql-spi")
api("io.github.graphql-java:graphql-java-annotations")
api("org.hypertrace.core.graphql:hypertrace-core-graphql-common-schema")

annotationProcessor("org.projectlombok:lombok")
compileOnly("org.projectlombok:lombok")

implementation("org.slf4j:slf4j-api")
implementation("io.reactivex.rxjava3:rxjava")
implementation("org.hypertrace.config.service:label-application-rule-config-service-api")
implementation("com.google.protobuf:protobuf-java-util")
implementation("com.google.guava:guava")

implementation("org.hypertrace.core.graphql:hypertrace-core-graphql-context")
implementation("org.hypertrace.core.graphql:hypertrace-core-graphql-grpc-utils")
implementation("org.hypertrace.core.graphql:hypertrace-core-graphql-schema-utils")
implementation("org.hypertrace.core.graphql:hypertrace-core-graphql-rx-utils")
implementation("org.hypertrace.core.graphql:hypertrace-core-graphql-deserialization")

implementation(project(":hypertrace-graphql-service-config"))
}

tasks.test {
useJUnitPlatform()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.hypertrace.graphql.label.application.rules;

import org.hypertrace.core.graphql.spi.schema.GraphQlSchemaFragment;
import org.hypertrace.graphql.label.application.rules.schema.mutation.LabelApplicationRuleMutationSchema;
import org.hypertrace.graphql.label.application.rules.schema.query.LabelApplicationRuleQuerySchema;

public class LabelApplicationRuleSchemaFragment implements GraphQlSchemaFragment {

@Override
public String fragmentName() {
return "Label Application Rules Schema";
}

@Override
public Class<LabelApplicationRuleQuerySchema> annotatedQueryClass() {
return LabelApplicationRuleQuerySchema.class;
}

@Override
public Class<?> annotatedMutationClass() {
return LabelApplicationRuleMutationSchema.class;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.hypertrace.graphql.label.application.rules;

import com.google.inject.AbstractModule;
import com.google.inject.multibindings.Multibinder;
import org.hypertrace.core.graphql.spi.schema.GraphQlSchemaFragment;
import org.hypertrace.graphql.label.application.rules.dao.LabelApplicationRuleDaoModule;
import org.hypertrace.graphql.label.application.rules.deserialization.LabelApplicationRuleDeserializationModule;
import org.hypertrace.graphql.label.application.rules.request.LabelApplicationRuleRequestModule;

public class LabelApplicationRuleSchemaModule extends AbstractModule {
@Override
protected void configure() {
Multibinder.newSetBinder(binder(), GraphQlSchemaFragment.class)
.addBinding()
.to(LabelApplicationRuleSchemaFragment.class);

install(new LabelApplicationRuleDaoModule());
install(new LabelApplicationRuleRequestModule());
install(new LabelApplicationRuleDeserializationModule());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package org.hypertrace.graphql.label.application.rules.dao;

import io.grpc.CallCredentials;
import io.reactivex.rxjava3.core.Single;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import org.hypertrace.core.graphql.common.request.ContextualRequest;
import org.hypertrace.core.graphql.utils.grpc.GrpcChannelRegistry;
import org.hypertrace.core.graphql.utils.grpc.GrpcContextBuilder;
import org.hypertrace.graphql.config.HypertraceGraphQlServiceConfig;
import org.hypertrace.graphql.label.application.rules.request.LabelApplicationRuleCreateRequest;
import org.hypertrace.graphql.label.application.rules.request.LabelApplicationRuleUpdateRequest;
import org.hypertrace.graphql.label.application.rules.schema.query.LabelApplicationRuleResultSet;
import org.hypertrace.graphql.label.application.rules.schema.shared.LabelApplicationRule;
import org.hypertrace.label.application.rule.config.service.v1.GetLabelApplicationRulesRequest;
import org.hypertrace.label.application.rule.config.service.v1.LabelApplicationRuleConfigServiceGrpc;
import org.hypertrace.label.application.rule.config.service.v1.LabelApplicationRuleConfigServiceGrpc.LabelApplicationRuleConfigServiceFutureStub;

class LabelApplicationRuleConfigServiceDao implements LabelApplicationRuleDao {

private final LabelApplicationRuleConfigServiceFutureStub
labelApplicationRuleConfigServiceFutureStub;
private final GrpcContextBuilder grpcContextBuilder;
private final HypertraceGraphQlServiceConfig serviceConfig;
private final LabelApplicationRuleRequestConverter requestConverter;
private final LabelApplicationRuleResponseConverter responseConverter;

@Inject
LabelApplicationRuleConfigServiceDao(
HypertraceGraphQlServiceConfig serviceConfig,
CallCredentials credentials,
GrpcContextBuilder grpcContextBuilder,
GrpcChannelRegistry grpcChannelRegistry,
LabelApplicationRuleRequestConverter requestConverter,
LabelApplicationRuleResponseConverter responseConverter) {
this.grpcContextBuilder = grpcContextBuilder;
this.serviceConfig = serviceConfig;
this.requestConverter = requestConverter;
this.responseConverter = responseConverter;
this.labelApplicationRuleConfigServiceFutureStub =
LabelApplicationRuleConfigServiceGrpc.newFutureStub(
grpcChannelRegistry.forAddress(
serviceConfig.getConfigServiceHost(), serviceConfig.getConfigServicePort()))
.withCallCredentials(credentials);
}

@Override
public Single<LabelApplicationRule> createLabelApplicationRule(
LabelApplicationRuleCreateRequest request) {
return Single.fromFuture(
this.grpcContextBuilder
.build(request.context())
.call(
() ->
this.labelApplicationRuleConfigServiceFutureStub
.withDeadlineAfter(
serviceConfig.getConfigServiceTimeout().toMillis(),
TimeUnit.MILLISECONDS)
.createLabelApplicationRule(
this.requestConverter.convertCreationRequest(request))))
.flatMap(this.responseConverter::convertCreateLabelApplicationRuleResponse);
}

@Override
public Single<LabelApplicationRuleResultSet> getLabelApplicationRules(ContextualRequest request) {
return Single.fromFuture(
this.grpcContextBuilder
.build(request.context())
.call(
() ->
this.labelApplicationRuleConfigServiceFutureStub
.withDeadlineAfter(
serviceConfig.getConfigServiceTimeout().toMillis(),
TimeUnit.MILLISECONDS)
.getLabelApplicationRules(
GetLabelApplicationRulesRequest.getDefaultInstance())))
.flatMap(this.responseConverter::convertGetLabelApplicationsRuleResponse);
}

@Override
public Single<LabelApplicationRule> updateLabelApplicationRule(
LabelApplicationRuleUpdateRequest request) {
return Single.error(new UnsupportedOperationException("Not yet implemented"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.hypertrace.graphql.label.application.rules.dao;

import io.reactivex.rxjava3.core.Single;
import org.hypertrace.core.graphql.common.request.ContextualRequest;
import org.hypertrace.graphql.label.application.rules.request.LabelApplicationRuleCreateRequest;
import org.hypertrace.graphql.label.application.rules.request.LabelApplicationRuleUpdateRequest;
import org.hypertrace.graphql.label.application.rules.schema.query.LabelApplicationRuleResultSet;
import org.hypertrace.graphql.label.application.rules.schema.shared.LabelApplicationRule;

public interface LabelApplicationRuleDao {
Single<LabelApplicationRule> createLabelApplicationRule(
LabelApplicationRuleCreateRequest request);

Single<LabelApplicationRuleResultSet> getLabelApplicationRules(ContextualRequest request);

Single<LabelApplicationRule> updateLabelApplicationRule(
LabelApplicationRuleUpdateRequest request);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.hypertrace.graphql.label.application.rules.dao;

import com.google.inject.AbstractModule;
import io.grpc.CallCredentials;
import org.hypertrace.core.graphql.spi.config.GraphQlServiceConfig;
import org.hypertrace.core.graphql.utils.grpc.GrpcChannelRegistry;
import org.hypertrace.core.graphql.utils.grpc.GrpcContextBuilder;

public class LabelApplicationRuleDaoModule extends AbstractModule {
@Override
protected void configure() {
bind(LabelApplicationRuleDao.class).to(LabelApplicationRuleConfigServiceDao.class);
requireBinding(CallCredentials.class);
requireBinding(GraphQlServiceConfig.class);
requireBinding(GrpcChannelRegistry.class);
requireBinding(GrpcContextBuilder.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package org.hypertrace.graphql.label.application.rules.dao;

import java.util.stream.Collectors;
import org.hypertrace.graphql.label.application.rules.request.LabelApplicationRuleCreateRequest;
import org.hypertrace.label.application.rule.config.service.v1.CreateLabelApplicationRuleRequest;
import org.hypertrace.label.application.rule.config.service.v1.LabelApplicationRuleData;
import org.hypertrace.label.application.rule.config.service.v1.LabelApplicationRuleData.Action;
import org.hypertrace.label.application.rule.config.service.v1.LabelApplicationRuleData.CompositeCondition;
import org.hypertrace.label.application.rule.config.service.v1.LabelApplicationRuleData.Condition;
import org.hypertrace.label.application.rule.config.service.v1.LabelApplicationRuleData.LeafCondition;
import org.hypertrace.label.application.rule.config.service.v1.LabelApplicationRuleData.StringCondition;
import org.hypertrace.label.application.rule.config.service.v1.LabelApplicationRuleData.UnaryCondition;

class LabelApplicationRuleRequestConverter {
CreateLabelApplicationRuleRequest convertCreationRequest(
LabelApplicationRuleCreateRequest labelApplicationRuleCreateRequest) {
org.hypertrace.graphql.label.application.rules.schema.shared.LabelApplicationRuleData data =
labelApplicationRuleCreateRequest
.createLabelApplicationRuleRequest()
.labelApplicationRuleData();
return CreateLabelApplicationRuleRequest.newBuilder()
.setData(
LabelApplicationRuleData.newBuilder()
.setName(data.name())
.setMatchingCondition(convertMatchingCondition(data.condition()))
.setLabelAction(convertLabelAction(data.action())))
.build();
}

Condition convertMatchingCondition(
org.hypertrace.graphql.label.application.rules.schema.shared.Condition condition) {
switch (condition.conditionType()) {
case LEAF_CONDITION:
return Condition.newBuilder()
.setLeafCondition(convertLeafCondition(condition.leafCondition()))
.build();
case COMPOSITE_CONDITION:
return Condition.newBuilder()
.setCompositeCondition(convertCompositeCondition(condition.compositeCondition()))
.build();
default:
throw new IllegalArgumentException("Error when parsing matching condition");
}
}

Action convertLabelAction(
org.hypertrace.graphql.label.application.rules.schema.shared.Action action) {
Action.Builder actionBuilder = Action.newBuilder().addAllEntityTypes(action.entityTypes());

switch (action.operation()) {
case OPERATION_MERGE:
actionBuilder.setOperation(Action.Operation.OPERATION_MERGE);
break;
default:
throw new IllegalArgumentException("Unsupported Operation");
}

switch (action.valueType()) {
case STATIC_LABELS:
return actionBuilder
.setStaticLabels(
Action.StaticLabels.newBuilder().addAllIds(action.staticLabels().ids()).build())
.build();
case DYNAMIC_LABEL_KEY:
return actionBuilder.setDynamicLabelKey(action.dynamicLabelKey()).build();
default:
throw new IllegalArgumentException("Unsupported action value");
}
}

CompositeCondition convertCompositeCondition(
org.hypertrace.graphql.label.application.rules.schema.shared.CompositeCondition
compositeCondition) {
CompositeCondition.Builder compositeConditionBuilder =
CompositeCondition.newBuilder()
.addAllChildren(
compositeCondition.children().stream()
.map(this::convertLeafCondition)
.map(
leafCondition ->
Condition.newBuilder().setLeafCondition(leafCondition).build())
.collect(Collectors.toList()));
switch (compositeCondition.operator()) {
case LOGICAL_OPERATOR_AND:
return compositeConditionBuilder
.setOperator(CompositeCondition.LogicalOperator.LOGICAL_OPERATOR_AND)
.build();
case LOGICAL_OPERATOR_OR:
return compositeConditionBuilder
.setOperator(CompositeCondition.LogicalOperator.LOGICAL_OPERATOR_OR)
.build();
default:
throw new IllegalArgumentException("Composite Condition Conversion Failed");
}
}

LeafCondition convertLeafCondition(
org.hypertrace.graphql.label.application.rules.schema.shared.LeafCondition leafCondition) {
LeafCondition.Builder leafConditionBuilder =
LeafCondition.newBuilder()
.setKeyCondition(convertStringCondition(leafCondition.keyCondition()));
switch (leafCondition.valueCondition().valueConditionType()) {
case STRING_CONDITION:
return leafConditionBuilder
.setStringCondition(
convertStringCondition(leafCondition.valueCondition().stringCondition()))
.build();
case UNARY_CONDITION:
return leafConditionBuilder
.setUnaryCondition(
convertUnaryCondition(leafCondition.valueCondition().unaryCondition()))
.build();
default:
throw new IllegalArgumentException("Unsupported Leaf Condition");
}
}

StringCondition convertStringCondition(
org.hypertrace.graphql.label.application.rules.schema.shared.StringCondition
stringCondition) {
return StringCondition.newBuilder()
.setOperator(convertStringConditionOperator(stringCondition.operator()))
.setValue(stringCondition.value())
.build();
}

UnaryCondition convertUnaryCondition(
org.hypertrace.graphql.label.application.rules.schema.shared.UnaryCondition unaryCondition) {
return UnaryCondition.newBuilder()
.setOperator(convertUnaryOperator(unaryCondition.operator()))
.build();
}

StringCondition.Operator convertStringConditionOperator(
org.hypertrace.graphql.label.application.rules.schema.shared.StringCondition.Operator
operator) {
switch (operator) {
case OPERATOR_EQUALS:
return StringCondition.Operator.OPERATOR_EQUALS;
case OPERATOR_MATCHES_REGEX:
return StringCondition.Operator.OPERATOR_MATCHES_REGEX;
default:
throw new IllegalArgumentException("Unsupported String Condition Operator");
}
}

UnaryCondition.Operator convertUnaryOperator(
org.hypertrace.graphql.label.application.rules.schema.shared.UnaryCondition.Operator
operator) {
switch (operator) {
case OPERATOR_EXISTS:
return UnaryCondition.Operator.OPERATOR_EXISTS;
default:
throw new IllegalArgumentException("Unsupported Unary Condition Operator");
}
}
}
Loading