Search in sources :

Example 26 with RegistrationAssertion

use of org.eclipse.hono.util.RegistrationAssertion in project hono by eclipse.

the class CommandTargetMapperImpl method getTargetGatewayAndAdapterInstance.

@Override
public final Future<JsonObject> getTargetGatewayAndAdapterInstance(final String tenantId, final String deviceId, final SpanContext context) {
    Objects.requireNonNull(tenantId);
    Objects.requireNonNull(deviceId);
    final Span span = TracingHelper.buildChildSpan(tracer, context, "get target gateway and adapter instance", CommandTargetMapper.class.getSimpleName()).withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CONSUMER).withTag(TracingHelper.TAG_TENANT_ID, tenantId).withTag(TracingHelper.TAG_DEVICE_ID, deviceId).start();
    return registrationClient.assertRegistration(tenantId, deviceId, null, span.context()).map(RegistrationAssertion::getAuthorizedGateways).recover(t -> {
        LOG.debug("Error retrieving gateways authorized to act on behalf of device [tenant-id: {}, device-id: {}]", tenantId, deviceId, t);
        return Future.failedFuture(ServiceInvocationException.extractStatusCode(t) == HttpURLConnection.HTTP_NOT_FOUND ? new DeviceDisabledOrNotRegisteredException(tenantId, HttpURLConnection.HTTP_NOT_FOUND) : t);
    }).compose(viaGateways -> {
        return deviceConnectionInfo.getCommandHandlingAdapterInstances(tenantId, deviceId, new HashSet<>(viaGateways), span).compose(resultJson -> determineTargetInstanceJson(resultJson, deviceId, viaGateways, span));
    }).onFailure(t -> {
        LOG.debug("Error getting target gateway and adapter instance", t);
        TracingHelper.logError(span, t);
        Tags.HTTP_STATUS.set(span, ServiceInvocationException.extractStatusCode(t));
    }).onComplete(ar -> span.finish());
}
Also used : HttpURLConnection(java.net.HttpURLConnection) Logger(org.slf4j.Logger) Tracer(io.opentracing.Tracer) DeviceConnectionConstants(org.eclipse.hono.util.DeviceConnectionConstants) LoggerFactory(org.slf4j.LoggerFactory) ServerErrorException(org.eclipse.hono.client.ServerErrorException) CommandTargetMapper(org.eclipse.hono.commandrouter.CommandTargetMapper) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) ServiceInvocationException(org.eclipse.hono.client.ServiceInvocationException) MessageHelper(org.eclipse.hono.util.MessageHelper) Tags(io.opentracing.tag.Tags) Future(io.vertx.core.Future) DeviceConnectionInfo(org.eclipse.hono.deviceconnection.infinispan.client.DeviceConnectionInfo) SpanContext(io.opentracing.SpanContext) HashSet(java.util.HashSet) Objects(java.util.Objects) DeviceDisabledOrNotRegisteredException(org.eclipse.hono.client.registry.DeviceDisabledOrNotRegisteredException) JsonArray(io.vertx.core.json.JsonArray) List(java.util.List) DeviceRegistrationClient(org.eclipse.hono.client.registry.DeviceRegistrationClient) Span(io.opentracing.Span) JsonObject(io.vertx.core.json.JsonObject) TracingHelper(org.eclipse.hono.tracing.TracingHelper) CommandTargetMapper(org.eclipse.hono.commandrouter.CommandTargetMapper) DeviceDisabledOrNotRegisteredException(org.eclipse.hono.client.registry.DeviceDisabledOrNotRegisteredException) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) Span(io.opentracing.Span) HashSet(java.util.HashSet)

Example 27 with RegistrationAssertion

use of org.eclipse.hono.util.RegistrationAssertion in project hono by eclipse.

the class KafkaBasedCommandResponseSenderTest method testIfValidCommandResponseKafkaRecordIsSent.

@Test
void testIfValidCommandResponseKafkaRecordIsSent(final VertxTestContext ctx, final Vertx vertx) {
    // GIVEN a command response sender
    final String tenantId = "test-tenant";
    final String deviceId = "test-device";
    final String correlationId = UUID.randomUUID().toString();
    final String contentType = "text/plain";
    final String payload = "the-payload";
    final int status = 200;
    final String additionalHeader1Name = "testHeader1";
    final String additionalHeader1Value = "testHeader1Value";
    final String additionalHeader2Name = "testHeader2";
    final String additionalHeader2Value = "testHeader2Value";
    final Map<String, Object> additionalProperties = Map.of(additionalHeader1Name, additionalHeader1Value, additionalHeader2Name, additionalHeader2Value);
    final CommandResponse commandResponse = CommandResponse.fromAddressAndCorrelationId(String.format("%s/%s/%s", CommandConstants.COMMAND_RESPONSE_ENDPOINT, tenantId, Commands.getDeviceFacingReplyToId("", deviceId, MessagingType.kafka)), correlationId, Buffer.buffer(payload), contentType, status);
    commandResponse.setAdditionalProperties(additionalProperties);
    final Span span = TracingMockSupport.mockSpan();
    final Tracer tracer = TracingMockSupport.mockTracer(span);
    final var mockProducer = KafkaClientUnitTestHelper.newMockProducer(true);
    final var factory = CachingKafkaProducerFactory.testFactory(vertx, (n, c) -> KafkaClientUnitTestHelper.newKafkaProducer(mockProducer));
    final var sender = new KafkaBasedCommandResponseSender(vertx, factory, kafkaProducerConfig, tracer);
    final TenantObject tenant = TenantObject.from(tenantId);
    tenant.setResourceLimits(new ResourceLimits().setMaxTtlCommandResponse(10L));
    // WHEN sending a command response
    sender.sendCommandResponse(tenant, new RegistrationAssertion(deviceId), commandResponse, NoopSpan.INSTANCE.context()).onComplete(ctx.succeeding(t -> {
        ctx.verify(() -> {
            // THEN the producer record is created from the given values...
            final ProducerRecord<String, Buffer> record = mockProducer.history().get(0);
            assertThat(record.key()).isEqualTo(deviceId);
            assertThat(record.topic()).isEqualTo(new HonoTopic(HonoTopic.Type.COMMAND_RESPONSE, tenantId).toString());
            assertThat(record.value().toString()).isEqualTo(payload);
            // Verify if the record contains the necessary headers.
            final Headers headers = record.headers();
            KafkaClientUnitTestHelper.assertUniqueHeaderWithExpectedValue(headers, MessageHelper.APP_PROPERTY_TENANT_ID, tenantId);
            KafkaClientUnitTestHelper.assertUniqueHeaderWithExpectedValue(headers, MessageHelper.APP_PROPERTY_DEVICE_ID, deviceId);
            KafkaClientUnitTestHelper.assertUniqueHeaderWithExpectedValue(headers, MessageHelper.SYS_PROPERTY_CORRELATION_ID, correlationId);
            KafkaClientUnitTestHelper.assertUniqueHeaderWithExpectedValue(headers, MessageHelper.APP_PROPERTY_STATUS, status);
            KafkaClientUnitTestHelper.assertUniqueHeaderWithExpectedValue(headers, MessageHelper.SYS_PROPERTY_CONTENT_TYPE, contentType);
            final var creationTimeHeader = headers.headers(MessageHelper.SYS_PROPERTY_CREATION_TIME);
            assertThat(creationTimeHeader).hasSize(1);
            final Long creationTimeMillis = Json.decodeValue(Buffer.buffer(creationTimeHeader.iterator().next().value()), Long.class);
            assertThat(creationTimeMillis).isGreaterThan(0L);
            KafkaClientUnitTestHelper.assertUniqueHeaderWithExpectedValue(headers, MessageHelper.SYS_HEADER_PROPERTY_TTL, 10000L);
            KafkaClientUnitTestHelper.assertUniqueHeaderWithExpectedValue(headers, additionalHeader1Name, additionalHeader1Value);
            KafkaClientUnitTestHelper.assertUniqueHeaderWithExpectedValue(headers, additionalHeader2Name, additionalHeader2Value);
            verify(span).finish();
        });
        ctx.completeNow();
    }));
}
Also used : VertxTestContext(io.vertx.junit5.VertxTestContext) BeforeEach(org.junit.jupiter.api.BeforeEach) Json(io.vertx.core.json.Json) ProducerRecord(org.apache.kafka.clients.producer.ProducerRecord) MessagingKafkaProducerConfigProperties(org.eclipse.hono.client.kafka.producer.MessagingKafkaProducerConfigProperties) ArgumentMatchers.eq(org.mockito.ArgumentMatchers.eq) Headers(org.apache.kafka.common.header.Headers) HashMap(java.util.HashMap) Commands(org.eclipse.hono.client.command.Commands) MessagingType(org.eclipse.hono.util.MessagingType) EventBus(io.vertx.core.eventbus.EventBus) ExtendWith(org.junit.jupiter.api.extension.ExtendWith) Mockito.verifyNoMoreInteractions(org.mockito.Mockito.verifyNoMoreInteractions) Map(java.util.Map) TracingMockSupport(org.eclipse.hono.test.TracingMockSupport) CommandConstants(org.eclipse.hono.util.CommandConstants) KafkaClientUnitTestHelper(org.eclipse.hono.kafka.test.KafkaClientUnitTestHelper) TenantChangeNotification(org.eclipse.hono.notification.deviceregistry.TenantChangeNotification) ResourceLimits(org.eclipse.hono.util.ResourceLimits) Tracer(io.opentracing.Tracer) CachingKafkaProducerFactory(org.eclipse.hono.client.kafka.producer.CachingKafkaProducerFactory) Vertx(io.vertx.core.Vertx) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) Mockito.when(org.mockito.Mockito.when) UUID(java.util.UUID) Truth.assertThat(com.google.common.truth.Truth.assertThat) MessageHelper(org.eclipse.hono.util.MessageHelper) VertxExtension(io.vertx.junit5.VertxExtension) Mockito.verify(org.mockito.Mockito.verify) CommandResponse(org.eclipse.hono.client.command.CommandResponse) TenantObject(org.eclipse.hono.util.TenantObject) Test(org.junit.jupiter.api.Test) HonoTopic(org.eclipse.hono.client.kafka.HonoTopic) Buffer(io.vertx.core.buffer.Buffer) VertxMockSupport(org.eclipse.hono.test.VertxMockSupport) Span(io.opentracing.Span) NotificationEventBusSupport(org.eclipse.hono.notification.NotificationEventBusSupport) NoopSpan(io.opentracing.noop.NoopSpan) Mockito.mock(org.mockito.Mockito.mock) Tracer(io.opentracing.Tracer) Headers(org.apache.kafka.common.header.Headers) CommandResponse(org.eclipse.hono.client.command.CommandResponse) HonoTopic(org.eclipse.hono.client.kafka.HonoTopic) Span(io.opentracing.Span) NoopSpan(io.opentracing.noop.NoopSpan) TenantObject(org.eclipse.hono.util.TenantObject) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) ResourceLimits(org.eclipse.hono.util.ResourceLimits) ProducerRecord(org.apache.kafka.clients.producer.ProducerRecord) TenantObject(org.eclipse.hono.util.TenantObject) Test(org.junit.jupiter.api.Test)

Example 28 with RegistrationAssertion

use of org.eclipse.hono.util.RegistrationAssertion in project hono by eclipse.

the class KafkaBasedCommandContext method sendDeliveryFailureCommandResponseMessage.

private Future<Void> sendDeliveryFailureCommandResponseMessage(final int status, final String error, final Span span, final Throwable cause) {
    final JsonObject payloadJson = new JsonObject();
    payloadJson.put("error", error != null ? error : "");
    final String correlationId = getCorrelationId();
    if (correlationId == null) {
        TracingHelper.logError(span, "can't send command response message - no correlation id set");
        return Future.failedFuture("missing correlation id");
    }
    final CommandResponse commandResponse = new CommandResponse(command.getTenant(), command.getDeviceId(), payloadJson.toBuffer(), CommandConstants.CONTENT_TYPE_DELIVERY_FAILURE_NOTIFICATION, status, correlationId, "", MessagingType.kafka);
    commandResponse.setAdditionalProperties(Collections.unmodifiableMap(command.getDeliveryFailureNotificationProperties()));
    return commandResponseSender.sendCommandResponse(// try to retrieve tenant configuration from context
    Optional.ofNullable(get(KEY_TENANT_CONFIG)).filter(TenantObject.class::isInstance).map(TenantObject.class::cast).orElseGet(() -> TenantObject.from(command.getTenant())), new RegistrationAssertion(command.getDeviceId()), commandResponse, span.context()).onFailure(thr -> {
        LOG.debug("failed to publish command response [{}]", commandResponse, thr);
        TracingHelper.logError(span, "failed to publish command response message", thr);
    }).onSuccess(v -> {
        LOG.debug("published error command response [{}, cause: {}]", commandResponse, cause != null ? cause.getMessage() : error);
        span.log("published error command response");
    });
}
Also used : HttpURLConnection(java.net.HttpURLConnection) LoggerFactory(org.slf4j.LoggerFactory) ClientErrorException(org.eclipse.hono.client.ClientErrorException) ServiceInvocationException(org.eclipse.hono.client.ServiceInvocationException) CommandResponseSender(org.eclipse.hono.client.command.CommandResponseSender) Tags(io.opentracing.tag.Tags) CommandAlreadyProcessedException(org.eclipse.hono.client.command.CommandAlreadyProcessedException) MessagingType(org.eclipse.hono.util.MessagingType) StatusCodeMapper(org.eclipse.hono.client.StatusCodeMapper) JsonObject(io.vertx.core.json.JsonObject) TracingHelper(org.eclipse.hono.tracing.TracingHelper) CommandConstants(org.eclipse.hono.util.CommandConstants) Logger(org.slf4j.Logger) CommandToBeReprocessedException(org.eclipse.hono.client.command.CommandToBeReprocessedException) CommandContext(org.eclipse.hono.client.command.CommandContext) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) KafkaRecordHelper(org.eclipse.hono.client.kafka.KafkaRecordHelper) Future(io.vertx.core.Future) CommandResponse(org.eclipse.hono.client.command.CommandResponse) TenantObject(org.eclipse.hono.util.TenantObject) Objects(java.util.Objects) MapBasedExecutionContext(org.eclipse.hono.util.MapBasedExecutionContext) Optional(java.util.Optional) Span(io.opentracing.Span) Collections(java.util.Collections) TenantObject(org.eclipse.hono.util.TenantObject) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) JsonObject(io.vertx.core.json.JsonObject) CommandResponse(org.eclipse.hono.client.command.CommandResponse)

Example 29 with RegistrationAssertion

use of org.eclipse.hono.util.RegistrationAssertion in project hono by eclipse.

the class AbstractProtocolAdapterBase method sendTtdEvent.

@Override
public final Future<Void> sendTtdEvent(final String tenant, final String deviceId, final Device authenticatedDevice, final Integer ttd, final SpanContext context) {
    Objects.requireNonNull(tenant);
    Objects.requireNonNull(deviceId);
    Objects.requireNonNull(ttd);
    final Future<RegistrationAssertion> tokenTracker = getRegistrationAssertion(tenant, deviceId, authenticatedDevice, context);
    final Future<TenantObject> tenantConfigTracker = getTenantConfiguration(tenant, context);
    return CompositeFuture.all(tokenTracker, tenantConfigTracker).compose(ok -> {
        if (tenantConfigTracker.result().isAdapterEnabled(getTypeName())) {
            final Map<String, Object> props = new HashMap<>();
            props.put(MessageHelper.APP_PROPERTY_ORIG_ADAPTER, getTypeName());
            props.put(MessageHelper.APP_PROPERTY_QOS, QoS.AT_LEAST_ONCE.ordinal());
            props.put(MessageHelper.APP_PROPERTY_DEVICE_TTD, ttd);
            return getEventSender(tenantConfigTracker.result()).sendEvent(tenantConfigTracker.result(), tokenTracker.result(), EventConstants.CONTENT_TYPE_EMPTY_NOTIFICATION, null, props, context).onSuccess(s -> log.debug("successfully sent TTD notification [tenant: {}, device-id: {}, TTD: {}]", tenant, deviceId, ttd)).onFailure(t -> log.debug("failed to send TTD notification [tenant: {}, device-id: {}, TTD: {}]", tenant, deviceId, ttd, t));
        } else {
            // this adapter is not enabled for the tenant
            return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_FORBIDDEN));
        }
    });
}
Also used : HttpURLConnection(java.net.HttpURLConnection) DecodeException(io.vertx.core.json.DecodeException) Context(io.vertx.core.Context) NoopResourceLimitChecks(org.eclipse.hono.adapter.resourcelimits.NoopResourceLimitChecks) TelemetrySender(org.eclipse.hono.client.telemetry.TelemetrySender) MessagingType(org.eclipse.hono.util.MessagingType) Map(java.util.Map) CredentialsClient(org.eclipse.hono.client.registry.CredentialsClient) ResourceIdentifier(org.eclipse.hono.util.ResourceIdentifier) JsonObject(io.vertx.core.json.JsonObject) EventSender(org.eclipse.hono.client.telemetry.EventSender) CommandContext(org.eclipse.hono.client.command.CommandContext) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) HttpResponseStatus(io.netty.handler.codec.http.HttpResponseStatus) TenantClient(org.eclipse.hono.client.registry.TenantClient) MessageHelper(org.eclipse.hono.util.MessageHelper) ServiceBaseUtils(org.eclipse.hono.service.util.ServiceBaseUtils) EventConstants(org.eclipse.hono.util.EventConstants) Future(io.vertx.core.Future) Device(org.eclipse.hono.auth.Device) Objects(java.util.Objects) TrustOptions(io.vertx.core.net.TrustOptions) List(java.util.List) Buffer(io.vertx.core.buffer.Buffer) CommandRouterClient(org.eclipse.hono.client.command.CommandRouterClient) Optional(java.util.Optional) QoS(org.eclipse.hono.util.QoS) ConnectionLimitManager(org.eclipse.hono.adapter.limiting.ConnectionLimitManager) Lifecycle(org.eclipse.hono.util.Lifecycle) HashMap(java.util.HashMap) ClientErrorException(org.eclipse.hono.client.ClientErrorException) TenantDisabledOrNotRegisteredException(org.eclipse.hono.client.registry.TenantDisabledOrNotRegisteredException) ConnectionEventProducer(org.eclipse.hono.adapter.monitoring.ConnectionEventProducer) ServiceInvocationException(org.eclipse.hono.client.ServiceInvocationException) CommandResponseSender(org.eclipse.hono.client.command.CommandResponseSender) ArrayList(java.util.ArrayList) DeviceDisabledOrNotRegisteredException(org.eclipse.hono.client.registry.DeviceDisabledOrNotRegisteredException) CompositeFuture(io.vertx.core.CompositeFuture) Status(io.vertx.ext.healthchecks.Status) HealthCheckHandler(io.vertx.ext.healthchecks.HealthCheckHandler) DeviceRegistrationClient(org.eclipse.hono.client.registry.DeviceRegistrationClient) GatewayDisabledOrNotRegisteredException(org.eclipse.hono.client.registry.GatewayDisabledOrNotRegisteredException) TelemetryExecutionContext(org.eclipse.hono.util.TelemetryExecutionContext) Strings(org.eclipse.hono.util.Strings) ProtocolAdapterProperties(org.eclipse.hono.config.ProtocolAdapterProperties) Promise(io.vertx.core.Promise) Vertx(io.vertx.core.Vertx) Sample(io.micrometer.core.instrument.Timer.Sample) CommandResponse(org.eclipse.hono.client.command.CommandResponse) TenantObject(org.eclipse.hono.util.TenantObject) SpanContext(io.opentracing.SpanContext) CommandConsumerFactory(org.eclipse.hono.client.command.CommandConsumerFactory) ValidityBasedTrustOptions(org.eclipse.hono.service.auth.ValidityBasedTrustOptions) ServiceClient(org.eclipse.hono.client.util.ServiceClient) ConnectionAttemptOutcome(org.eclipse.hono.service.metric.MetricsTags.ConnectionAttemptOutcome) AbstractServiceBase(org.eclipse.hono.service.AbstractServiceBase) ResourceLimitChecks(org.eclipse.hono.adapter.resourcelimits.ResourceLimitChecks) TenantObject(org.eclipse.hono.util.TenantObject) HashMap(java.util.HashMap) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) ClientErrorException(org.eclipse.hono.client.ClientErrorException) JsonObject(io.vertx.core.json.JsonObject) TenantObject(org.eclipse.hono.util.TenantObject)

Example 30 with RegistrationAssertion

use of org.eclipse.hono.util.RegistrationAssertion in project hono by eclipse.

the class ProtonBasedCommandResponseSenderTest method testCommandResponseMessageHasCreationTimeAndTtl.

/**
 * Verifies that command response messages being sent downstream contain a creation-time
 * and a time-to-live as defined at the tenant level.
 */
@Test
public void testCommandResponseMessageHasCreationTimeAndTtl() {
    final var now = Instant.now();
    final TenantObject tenant = TenantObject.from(TENANT_ID);
    tenant.setResourceLimits(new ResourceLimits().setMaxTtlCommandResponse(10L));
    when(protonSender.sendQueueFull()).thenReturn(Boolean.FALSE);
    when(protonSender.send(any(Message.class), VertxMockSupport.anyHandler())).thenReturn(mock(ProtonDelivery.class));
    // WHEN sending a command response message
    final CommandResponse commandResponse = CommandResponse.fromRequestId(Commands.encodeRequestIdParameters(CORRELATION_ID, REPLY_TO_ID, DEVICE_ID, MessagingType.amqp), TENANT_ID, DEVICE_ID, null, null, HttpURLConnection.HTTP_OK);
    sender.sendCommandResponse(tenant, new RegistrationAssertion(DEVICE_ID), commandResponse, span.context());
    final ArgumentCaptor<Message> downstreamMessage = ArgumentCaptor.forClass(Message.class);
    verify(protonSender).send(downstreamMessage.capture(), VertxMockSupport.anyHandler());
    // THEN the message being sent contains a creation-time
    assertThat(downstreamMessage.getValue().getCreationTime()).isAtLeast(now.toEpochMilli());
    // and a TTL
    assertThat(downstreamMessage.getValue().getTtl()).isEqualTo(10_000L);
    // and a 200 status code
    assertThat(MessageHelper.getStatus(downstreamMessage.getValue())).isEqualTo(HttpURLConnection.HTTP_OK);
}
Also used : TenantObject(org.eclipse.hono.util.TenantObject) Message(org.apache.qpid.proton.message.Message) ProtonDelivery(io.vertx.proton.ProtonDelivery) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) ResourceLimits(org.eclipse.hono.util.ResourceLimits) CommandResponse(org.eclipse.hono.client.command.CommandResponse) Test(org.junit.jupiter.api.Test)

Aggregations

RegistrationAssertion (org.eclipse.hono.util.RegistrationAssertion)42 Future (io.vertx.core.Future)31 HttpURLConnection (java.net.HttpURLConnection)29 MessageHelper (org.eclipse.hono.util.MessageHelper)29 Map (java.util.Map)27 Span (io.opentracing.Span)26 TenantObject (org.eclipse.hono.util.TenantObject)26 Buffer (io.vertx.core.buffer.Buffer)24 Constants (org.eclipse.hono.util.Constants)22 ServerErrorException (org.eclipse.hono.client.ServerErrorException)21 Device (org.eclipse.hono.auth.Device)20 Test (org.junit.jupiter.api.Test)20 ClientErrorException (org.eclipse.hono.client.ClientErrorException)18 Handler (io.vertx.core.Handler)17 Objects (java.util.Objects)17 ResourceIdentifier (org.eclipse.hono.util.ResourceIdentifier)17 HashMap (java.util.HashMap)16 Command (org.eclipse.hono.client.command.Command)16 ArgumentMatchers.anyString (org.mockito.ArgumentMatchers.anyString)16 SpanContext (io.opentracing.SpanContext)15