Expand Dapr metadata API (#1057)

* Expand Dapr metadata API

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Adding extended attributes to Dapr metadata

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Add tests for GRPC

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

---------

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>
Co-authored-by: Artur Ciocanu <ciocanu@adobe.com>
This commit is contained in:
artur-ciocanu 2024-06-25 14:03:21 -07:00 committed by GitHub
parent d9cfba7e8d
commit 653ba7e707
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 320 additions and 30 deletions

View File

@ -16,6 +16,8 @@ package io.dapr.client;
import com.google.common.base.Strings;
import com.google.protobuf.ByteString;
import com.google.protobuf.Empty;
import io.dapr.client.domain.AppConnectionPropertiesHealthMetadata;
import io.dapr.client.domain.AppConnectionPropertiesMetadata;
import io.dapr.client.domain.BulkPublishEntry;
import io.dapr.client.domain.BulkPublishRequest;
import io.dapr.client.domain.BulkPublishResponse;
@ -30,6 +32,7 @@ import io.dapr.client.domain.GetBulkStateRequest;
import io.dapr.client.domain.GetConfigurationRequest;
import io.dapr.client.domain.GetSecretRequest;
import io.dapr.client.domain.GetStateRequest;
import io.dapr.client.domain.HttpEndpointMetadata;
import io.dapr.client.domain.HttpExtension;
import io.dapr.client.domain.InvokeBindingRequest;
import io.dapr.client.domain.InvokeMethodRequest;
@ -62,6 +65,9 @@ import io.dapr.utils.TypeRef;
import io.dapr.v1.CommonProtos;
import io.dapr.v1.DaprGrpc;
import io.dapr.v1.DaprProtos;
import io.dapr.v1.DaprProtos.AppConnectionHealthProperties;
import io.dapr.v1.DaprProtos.AppConnectionProperties;
import io.dapr.v1.DaprProtos.MetadataHTTPEndpoint;
import io.dapr.v1.DaprProtos.PubsubSubscription;
import io.dapr.v1.DaprProtos.PubsubSubscriptionRule;
import io.dapr.v1.DaprProtos.RegisteredComponents;
@ -1256,8 +1262,21 @@ public class DaprClientImpl extends AbstractDaprClient {
});
}
private DaprMetadata buildDaprMetadata(
DaprProtos.GetMetadataResponse response) throws IOException {
private DaprMetadata buildDaprMetadata(DaprProtos.GetMetadataResponse response) throws IOException {
String id = response.getId();
String runtimeVersion = response.getRuntimeVersion();
List<String> enabledFeatures = response.getEnabledFeaturesList();
Map<String, String> attributes = response.getExtendedMetadataMap();
List<ComponentMetadata> components = getComponents(response);
List<HttpEndpointMetadata> httpEndpoints = getHttpEndpoints(response);
List<SubscriptionMetadata> subscriptions = getSubscriptions(response);
AppConnectionPropertiesMetadata appConnectionProperties = getAppConnectionProperties(response);
return new DaprMetadata(id, runtimeVersion, enabledFeatures, attributes, components, httpEndpoints, subscriptions,
appConnectionProperties);
}
private List<ComponentMetadata> getComponents(DaprProtos.GetMetadataResponse response) {
List<RegisteredComponents> registeredComponentsList = response.getRegisteredComponentsList();
List<ComponentMetadata> components = new ArrayList<>();
@ -1265,7 +1284,12 @@ public class DaprClientImpl extends AbstractDaprClient {
components.add(new ComponentMetadata(rc.getName(), rc.getType(), rc.getVersion()));
}
return components;
}
private List<SubscriptionMetadata> getSubscriptions(DaprProtos.GetMetadataResponse response) {
List<PubsubSubscription> subscriptionsList = response.getSubscriptionsList();
List<SubscriptionMetadata> subscriptions = new ArrayList<>();
for (PubsubSubscription s : subscriptionsList) {
List<PubsubSubscriptionRule> rulesList = s.getRules().getRulesList();
@ -1276,6 +1300,45 @@ public class DaprClientImpl extends AbstractDaprClient {
subscriptions.add(new SubscriptionMetadata(s.getTopic(), s.getPubsubName(), s.getDeadLetterTopic(), rules));
}
return new DaprMetadata(response.getId(), response.getRuntimeVersion(), components, subscriptions);
return subscriptions;
}
}
private List<HttpEndpointMetadata> getHttpEndpoints(DaprProtos.GetMetadataResponse response) {
List<MetadataHTTPEndpoint> httpEndpointsList = response.getHttpEndpointsList();
List<HttpEndpointMetadata> httpEndpoints = new ArrayList<>();
for (MetadataHTTPEndpoint m : httpEndpointsList) {
httpEndpoints.add(new HttpEndpointMetadata(m.getName()));
}
return httpEndpoints;
}
private AppConnectionPropertiesMetadata getAppConnectionProperties(DaprProtos.GetMetadataResponse response) {
AppConnectionProperties appConnectionProperties = response.getAppConnectionProperties();
int port = appConnectionProperties.getPort();
String protocol = appConnectionProperties.getProtocol();
String channelAddress = appConnectionProperties.getChannelAddress();
int maxConcurrency = appConnectionProperties.getMaxConcurrency();
AppConnectionPropertiesHealthMetadata health = getAppConnectionPropertiesHealth(appConnectionProperties);
return new AppConnectionPropertiesMetadata(port, protocol, channelAddress, maxConcurrency, health);
}
private AppConnectionPropertiesHealthMetadata getAppConnectionPropertiesHealth(
AppConnectionProperties appConnectionProperties) {
if (!appConnectionProperties.hasHealth()) {
return null;
}
AppConnectionHealthProperties health = appConnectionProperties.getHealth();
String healthCheckPath = health.getHealthCheckPath();
String healthProbeInterval = health.getHealthProbeInterval();
String healthProbeTimeout = health.getHealthProbeTimeout();
int healthThreshold = health.getHealthThreshold();
return new AppConnectionPropertiesHealthMetadata(healthCheckPath, healthProbeInterval, healthProbeTimeout,
healthThreshold);
}
}

View File

@ -0,0 +1,55 @@
/*
* Copyright 2024 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.client.domain;
public final class AppConnectionPropertiesHealthMetadata {
private final String healthCheckPath;
private final String healthProbeInterval;
private final String healthProbeTimeout;
private final int healthThreshold;
/**
* Constructor for a AppConnectionPropertiesHealthMetadata.
*
* @param healthCheckPath of the application
* @param healthProbeInterval time interval between health probes
* @param healthProbeTimeout timeout for each health probe
* @param healthThreshold max number of failed health probes
*/
public AppConnectionPropertiesHealthMetadata(String healthCheckPath, String healthProbeInterval,
String healthProbeTimeout, int healthThreshold) {
this.healthCheckPath = healthCheckPath;
this.healthProbeInterval = healthProbeInterval;
this.healthProbeTimeout = healthProbeTimeout;
this.healthThreshold = healthThreshold;
}
public String getHealthCheckPath() {
return healthCheckPath;
}
public String getHealthProbeInterval() {
return healthProbeInterval;
}
public String getHealthProbeTimeout() {
return healthProbeTimeout;
}
public int getHealthThreshold() {
return healthThreshold;
}
}

View File

@ -0,0 +1,62 @@
/*
* Copyright 2024 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.client.domain;
public final class AppConnectionPropertiesMetadata {
private final int port;
private final String protocol;
private final String channelAddress;
private final int maxConcurrency;
private final AppConnectionPropertiesHealthMetadata health;
/**
* Constructor for a AppConnectionPropertiesMetadata.
*
* @param port of the application
* @param protocol of the application
* @param channelAddress host address of the application
* @param maxConcurrency number of concurrent requests the app can handle
* @param health health check details of the application
*/
public AppConnectionPropertiesMetadata(int port, String protocol, String channelAddress, int maxConcurrency,
AppConnectionPropertiesHealthMetadata health) {
this.port = port;
this.protocol = protocol;
this.channelAddress = channelAddress;
this.maxConcurrency = maxConcurrency;
this.health = health;
}
public int getPort() {
return port;
}
public String getProtocol() {
return protocol;
}
public String getChannelAddress() {
return channelAddress;
}
public int getMaxConcurrency() {
return maxConcurrency;
}
public AppConnectionPropertiesHealthMetadata getHealth() {
return health;
}
}

View File

@ -15,32 +15,46 @@ package io.dapr.client.domain;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Map;
/**
* DaprMetadata describes the Dapr Metadata.
*/
public final class DaprMetadata {
private String id;
private String runtimeVersion;
private List<ComponentMetadata> components;
private List<SubscriptionMetadata> subscriptions;
private final String id;
private final String runtimeVersion;
private final List<String> enabledFeatures;
private final Map<String, String> attributes;
private final List<ComponentMetadata> components;
private final List<HttpEndpointMetadata> httpEndpoints;
private final List<SubscriptionMetadata> subscriptions;
private final AppConnectionPropertiesMetadata appConnectionProperties;
/**
* Constructor for a DaprMetadata.
*
* @param id of the application
* @param runtimeVersion Dapr version
* @param components list of registered componnets
* @param enabledFeatures list of enabled features
* @param attributes map of extended attributes
* @param components list of registered components
* @param httpEndpoints list of registered http endpoints
* @param subscriptions list of registered subscription
* @param appConnectionProperties connection properties of the application
*/
public DaprMetadata(String id, String runtimeVersion, List<ComponentMetadata> components,
List<SubscriptionMetadata> subscriptions) {
public DaprMetadata(String id, String runtimeVersion, List<String> enabledFeatures, Map<String, String> attributes,
List<ComponentMetadata> components, List<HttpEndpointMetadata> httpEndpoints,
List<SubscriptionMetadata> subscriptions, AppConnectionPropertiesMetadata appConnectionProperties) {
this.id = id;
this.runtimeVersion = runtimeVersion;
this.enabledFeatures = enabledFeatures == null ? Collections.emptyList() :
Collections.unmodifiableList(enabledFeatures);
this.attributes = attributes == null ? Collections.emptyMap() : Collections.unmodifiableMap(attributes);
this.components = components == null ? Collections.emptyList() : Collections.unmodifiableList(components);
this.httpEndpoints = httpEndpoints == null ? Collections.emptyList() : Collections.unmodifiableList(httpEndpoints);
this.subscriptions = subscriptions == null ? Collections.emptyList() : Collections.unmodifiableList(subscriptions);
this.appConnectionProperties = appConnectionProperties;
}
public String getId() {
@ -51,12 +65,28 @@ public final class DaprMetadata {
return runtimeVersion;
}
public List<String> getEnabledFeatures() {
return enabledFeatures;
}
public Map<String, String> getAttributes() {
return attributes;
}
public List<ComponentMetadata> getComponents() {
return components;
}
public List<HttpEndpointMetadata> getHttpEndpoints() {
return httpEndpoints;
}
public List<SubscriptionMetadata> getSubscriptions() {
return subscriptions;
}
public AppConnectionPropertiesMetadata getAppConnectionProperties() {
return appConnectionProperties;
}
}

View File

@ -0,0 +1,33 @@
/*
* Copyright 2024 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.client.domain;
public final class HttpEndpointMetadata {
private final String name;
/**
* Constructor for a HttpEndpointMetadata.
*
* @param name of the HTTP endpoint
*/
public HttpEndpointMetadata(String name) {
this.name = name;
}
public String getName() {
return name;
}
}

View File

@ -16,28 +16,18 @@ package io.dapr.client;
import com.google.protobuf.Any;
import com.google.protobuf.ByteString;
import com.google.protobuf.Empty;
import io.dapr.client.domain.ConfigurationItem;
import io.dapr.client.domain.DaprMetadata;
import io.dapr.client.domain.DeleteStateRequest;
import io.dapr.client.domain.ExecuteStateTransactionRequest;
import io.dapr.client.domain.GetBulkStateRequest;
import io.dapr.client.domain.GetStateRequest;
import io.dapr.client.domain.PublishEventRequest;
import io.dapr.client.domain.State;
import io.dapr.client.domain.StateOptions;
import io.dapr.client.domain.SubscribeConfigurationResponse;
import io.dapr.client.domain.TransactionalStateOperation;
import io.dapr.client.domain.UnsubscribeConfigurationRequest;
import io.dapr.client.domain.UnsubscribeConfigurationResponse;
import io.dapr.exceptions.DaprError;
import io.dapr.exceptions.DaprException;
import io.dapr.client.domain.*;
import io.dapr.serializer.DaprObjectSerializer;
import io.dapr.serializer.DefaultObjectSerializer;
import io.dapr.utils.TypeRef;
import io.dapr.v1.CommonProtos;
import io.dapr.v1.DaprGrpc;
import io.dapr.v1.DaprProtos;
import io.dapr.v1.DaprProtos.AppConnectionHealthProperties;
import io.dapr.v1.DaprProtos.AppConnectionProperties;
import io.dapr.v1.DaprProtos.MetadataHTTPEndpoint;
import io.dapr.v1.DaprProtos.PubsubSubscription;
import io.dapr.v1.DaprProtos.PubsubSubscriptionRules;
import io.dapr.v1.DaprProtos.RegisteredComponents;
import io.grpc.Status;
import io.grpc.StatusRuntimeException;
@ -2086,25 +2076,54 @@ public class DaprClientGrpcTest {
@Test
public void getMetadataTest() {
RegisteredComponents registeredComponents = DaprProtos.RegisteredComponents.newBuilder()
.setName("statestore")
.setType("state.redis")
.setVersion("v1")
.build();
DaprProtos.MetadataHTTPEndpoint httpEndpoint = DaprProtos.MetadataHTTPEndpoint.newBuilder()
.setName("httpEndpoint")
.build();
PubsubSubscriptionRules pubsubSubscriptionRules = DaprProtos.PubsubSubscriptionRules.newBuilder()
.addRules(DaprProtos.PubsubSubscriptionRule.newBuilder().setPath("/events").build())
.build();
PubsubSubscription pubsubSubscription = DaprProtos.PubsubSubscription.newBuilder()
.setDeadLetterTopic("")
.setPubsubName("pubsub")
.setTopic("topic")
.setRules(DaprProtos.PubsubSubscriptionRules.newBuilder()
.addRules(DaprProtos.PubsubSubscriptionRule.newBuilder().setPath("/events").build()).build())
.setRules(pubsubSubscriptionRules)
.build();
AppConnectionHealthProperties healthProperties = DaprProtos.AppConnectionHealthProperties.newBuilder()
.setHealthCheckPath("/health")
.setHealthProbeInterval("10s")
.setHealthProbeTimeout("5s")
.setHealthThreshold(1)
.build();
AppConnectionProperties appConnectionProperties = DaprProtos.AppConnectionProperties.newBuilder()
.setPort(8080)
.setProtocol("http")
.setChannelAddress("localhost")
.setMaxConcurrency(1)
.setHealth(healthProperties)
.build();
DaprProtos.GetMetadataResponse responseEnvelope = DaprProtos.GetMetadataResponse.newBuilder()
.setId("app")
.setRuntimeVersion("1.1x.x")
.addAllEnabledFeatures(Collections.emptyList())
.putAllExtendedMetadata(Collections.emptyMap())
.addAllRegisteredComponents(Collections.singletonList(registeredComponents))
.addAllHttpEndpoints(Collections.singletonList(httpEndpoint))
.addAllSubscriptions(Collections.singletonList(pubsubSubscription))
.setAppConnectionProperties(appConnectionProperties)
.build();
doAnswer((Answer<Void>) invocation -> {
StreamObserver<DaprProtos.GetMetadataResponse> observer = (StreamObserver<DaprProtos.GetMetadataResponse>) invocation
.getArguments()[1];
@ -2115,19 +2134,47 @@ public class DaprClientGrpcTest {
Mono<DaprMetadata> result = client.getMetadata();
DaprMetadata metadata = result.block();
assertNotNull(metadata);
assertEquals("app", metadata.getId());
assertEquals("1.1x.x", metadata.getRuntimeVersion());
assertEquals(0, metadata.getEnabledFeatures().size());
assertEquals(0, metadata.getAttributes().size());
// Components
assertEquals(1, metadata.getComponents().size());
assertEquals(registeredComponents.getName(), metadata.getComponents().get(0).getName());
assertEquals(registeredComponents.getVersion(), metadata.getComponents().get(0).getVersion());
assertEquals(registeredComponents.getType(), metadata.getComponents().get(0).getType());
// Subscriptions
assertEquals(1, metadata.getSubscriptions().size());
assertEquals(pubsubSubscription.getPubsubName(), metadata.getSubscriptions().get(0).getPubsubname());
assertEquals(pubsubSubscription.getTopic(), metadata.getSubscriptions().get(0).getTopic());
// Subscription Rules
assertEquals(1, metadata.getSubscriptions().get(0).getRules().size());
assertEquals(pubsubSubscription.getRules().getRules(0).getPath(), metadata.getSubscriptions().get(0).getRules().get(0).getPath());
// HTTP Endpoints
assertEquals(1, metadata.getHttpEndpoints().size());
assertEquals(httpEndpoint.getName(), metadata.getHttpEndpoints().get(0).getName());
// App Connection Properties
AppConnectionPropertiesMetadata appConnectionPropertiesMetadata = metadata.getAppConnectionProperties();
assertEquals(appConnectionProperties.getPort(), appConnectionPropertiesMetadata.getPort());
assertEquals(appConnectionProperties.getProtocol(), appConnectionPropertiesMetadata.getProtocol());
assertEquals(appConnectionProperties.getChannelAddress(), appConnectionPropertiesMetadata.getChannelAddress());
assertEquals(appConnectionProperties.getMaxConcurrency(), appConnectionPropertiesMetadata.getMaxConcurrency());
// App Connection Health Properties
AppConnectionPropertiesHealthMetadata healthMetadata = appConnectionPropertiesMetadata.getHealth();
assertEquals(healthProperties.getHealthCheckPath(), healthMetadata.getHealthCheckPath());
assertEquals(healthProperties.getHealthProbeInterval(), healthMetadata.getHealthProbeInterval());
assertEquals(healthProperties.getHealthProbeTimeout(), healthMetadata.getHealthProbeTimeout());
assertEquals(healthProperties.getHealthThreshold(), healthMetadata.getHealthThreshold());
}
@Test