Search in sources :

Example 1 with UnidirectionalEvent

use of io.github.microcks.domain.UnidirectionalEvent in project microcks by microcks.

the class AsyncMinionApp method onStart.

/**
 * Application startup method.
 */
void onStart(@Observes StartupEvent ev) {
    // We need to retrieve Keycloak server from Microcks config.
    KeycloakConfig config = microcksAPIConnector.getKeycloakConfig();
    logger.infof("Microcks Keycloak server url {%s} and realm {%s}", config.getAuthServerUrl(), config.getRealm());
    String keycloakEndpoint = config.getAuthServerUrl() + "/realms/" + config.getRealm() + "/protocol/openid-connect/token";
    if (!keycloakAuthURL.isEmpty() && keycloakAuthURL.get().length() > 0) {
        logger.infof("Use locally defined Keycloak Auth URL: %s", keycloakAuthURL);
        keycloakEndpoint = keycloakAuthURL.get() + "/realms/" + config.getRealm() + "/protocol/openid-connect/token";
    }
    try {
        // First retrieve an authentication token before fetching async messages to publish.
        String oauthToken;
        if (config.isEnabled()) {
            // We've got a full Keycloak config, attempt an authent.
            oauthToken = keycloakConnector.connectAndGetOAuthToken(keycloakEndpoint);
            logger.info("Authentication to Keycloak server succeed!");
        } else {
            // No realm config, probably a dev mode - use a fake token.
            oauthToken = "<anonymous-admin-token>";
            logger.info("Keycloak protection is not enabled, using a fake token");
        }
        int page = 0;
        boolean fetchServices = true;
        while (fetchServices) {
            List<Service> services = microcksAPIConnector.listServices("Bearer " + oauthToken, page, SERVICES_FETCH_SIZE);
            for (Service service : services) {
                logger.debug("Found service " + service.getName() + " - " + service.getVersion());
                if (service.getType().equals(ServiceType.EVENT)) {
                    // Find the operations matching this minion constraints..
                    List<Operation> operations = service.getOperations().stream().filter(o -> Arrays.asList(restrictedFrequencies).contains(o.getDefaultDelay())).filter(o -> o.getBindings().keySet().stream().anyMatch(Arrays.asList(supportedBindings)::contains)).collect(Collectors.toList());
                    if (operations.size() > 0) {
                        logger.info("Found " + operations.size() + " candidate operations in " + service.getName() + " - " + service.getVersion());
                        ServiceView serviceView = microcksAPIConnector.getService("Bearer " + oauthToken, service.getId(), true);
                        for (Operation operation : operations) {
                            AsyncMockDefinition mockDefinition = new AsyncMockDefinition(serviceView.getService(), operation, serviceView.getMessagesMap().get(operation.getName()).stream().filter(e -> e instanceof UnidirectionalEvent).map(e -> ((UnidirectionalEvent) e).getEventMessage()).collect(Collectors.toList()));
                            mockRepository.storeMockDefinition(mockDefinition);
                            schemaRegistry.updateRegistryForService(mockDefinition.getOwnerService());
                        }
                    }
                }
            }
            if (services.size() < SERVICES_FETCH_SIZE) {
                fetchServices = false;
            }
            page++;
        }
        logger.info("Starting scheduling of all producer jobs...");
        producerScheduler.scheduleAllProducerJobs();
    } catch (ConnectorException ce) {
        logger.error("Cannot authenticate to Keycloak server and thus enable to call Microcks API" + "to get Async APIs to mocks...", ce);
        throw new RuntimeException("Unable to start the Minion due to connection exception");
    } catch (IOException ioe) {
        logger.error("IOException while communicating with Keycloak or Microcks API", ioe);
        throw new RuntimeException("Unable to start the Minion due to IO exception");
    }
}
Also used : KeycloakConnector(io.github.microcks.minion.async.client.KeycloakConnector) Arrays(java.util.Arrays) RestClient(org.eclipse.microprofile.rest.client.inject.RestClient) Logger(org.jboss.logging.Logger) ServiceView(io.github.microcks.domain.ServiceView) MicrocksAPIConnector(io.github.microcks.minion.async.client.MicrocksAPIConnector) IOException(java.io.IOException) UnidirectionalEvent(io.github.microcks.domain.UnidirectionalEvent) ConnectorException(io.github.microcks.minion.async.client.ConnectorException) Collectors(java.util.stream.Collectors) KeycloakConfig(io.github.microcks.minion.async.client.KeycloakConfig) Inject(javax.inject.Inject) Service(io.github.microcks.domain.Service) List(java.util.List) Operation(io.github.microcks.domain.Operation) ServiceType(io.github.microcks.domain.ServiceType) Observes(javax.enterprise.event.Observes) Optional(java.util.Optional) ApplicationScoped(javax.enterprise.context.ApplicationScoped) StartupEvent(io.quarkus.runtime.StartupEvent) ConfigProperty(org.eclipse.microprofile.config.inject.ConfigProperty) ServiceView(io.github.microcks.domain.ServiceView) UnidirectionalEvent(io.github.microcks.domain.UnidirectionalEvent) Service(io.github.microcks.domain.Service) Operation(io.github.microcks.domain.Operation) IOException(java.io.IOException) ConnectorException(io.github.microcks.minion.async.client.ConnectorException) KeycloakConfig(io.github.microcks.minion.async.client.KeycloakConfig)

Example 2 with UnidirectionalEvent

use of io.github.microcks.domain.UnidirectionalEvent in project microcks by microcks.

the class ServiceChangeEventPublisher method onApplicationEvent.

@Override
@Async
public void onApplicationEvent(ServiceChangeEvent event) {
    log.debug("Received a ServiceChangeEvent on " + event.getServiceId());
    ServiceView serviceView = null;
    if (event.getChangeType() != ChangeType.DELETED) {
        Service service = serviceRepository.findById(event.getServiceId()).orElse(null);
        if (service != null) {
            // Put messages into a map where key is operation name.
            Map<String, List<? extends Exchange>> messagesMap = new HashMap<>();
            for (Operation operation : service.getOperations()) {
                if (service.getType() == ServiceType.EVENT) {
                    // If an event, we should explicitly retrieve event messages.
                    List<UnidirectionalEvent> events = messageService.getEventByOperation(IdBuilder.buildOperationId(service, operation));
                    messagesMap.put(operation.getName(), events);
                } else {
                    // Otherwise we have traditional request / response pairs.
                    List<RequestResponsePair> pairs = messageService.getRequestResponseByOperation(IdBuilder.buildOperationId(service, operation));
                    messagesMap.put(operation.getName(), pairs);
                }
            }
            serviceView = new ServiceView(service, messagesMap);
        }
    }
    // Build and send a ServiceViewChangeEvent that wraps ServiceView.
    ServiceViewChangeEvent serviceViewChangeEvent = new ServiceViewChangeEvent(event.getServiceId(), serviceView, event.getChangeType(), System.currentTimeMillis());
    kafkaTemplate.send("microcks-services-updates", event.getServiceId(), serviceViewChangeEvent);
    log.debug("Processing of ServiceChangeEvent done !");
}
Also used : RequestResponsePair(io.github.microcks.domain.RequestResponsePair) ServiceView(io.github.microcks.domain.ServiceView) ServiceViewChangeEvent(io.github.microcks.event.ServiceViewChangeEvent) HashMap(java.util.HashMap) UnidirectionalEvent(io.github.microcks.domain.UnidirectionalEvent) Service(io.github.microcks.domain.Service) MessageService(io.github.microcks.service.MessageService) Operation(io.github.microcks.domain.Operation) Exchange(io.github.microcks.domain.Exchange) List(java.util.List) Async(org.springframework.scheduling.annotation.Async)

Example 3 with UnidirectionalEvent

use of io.github.microcks.domain.UnidirectionalEvent in project microcks by microcks.

the class AsyncAPIImporter method getMessageDefinitions.

@Override
public List<Exchange> getMessageDefinitions(Service service, Operation operation) throws MockRepositoryImportException {
    List<Exchange> result = new ArrayList<>();
    // Retrieve default content type, defaulting to application/json.
    String defaultContentType = "application/json";
    if (spec.has("defaultContentType")) {
        defaultContentType = spec.get("defaultContentType").asText("application/json");
    }
    // Iterate on specification "channels" nodes.
    Iterator<Entry<String, JsonNode>> channels = spec.path("channels").fields();
    while (channels.hasNext()) {
        Entry<String, JsonNode> channel = channels.next();
        String channelName = channel.getKey();
        Map<String, Map<String, String>> pathParametersByExample = extractParametersByExample(channel.getValue());
        // Iterate on specification path, "verbs" nodes.
        Iterator<Entry<String, JsonNode>> verbs = channel.getValue().fields();
        while (verbs.hasNext()) {
            Entry<String, JsonNode> verb = verbs.next();
            String verbName = verb.getKey();
            // Find the correct operation.
            if (operation.getName().equals(verbName.toUpperCase() + " " + channelName.trim())) {
                JsonNode messageBody = verb.getValue().path("message");
                // If it's a $ref or multi-structure (oneOf, anyOf, allOf), then navigate to them.
                List<JsonNode> messageBodies = followRefsIfAny(messageBody);
                for (JsonNode extractedMsgBody : messageBodies) {
                    // Get message content type.
                    String contentType = defaultContentType;
                    if (extractedMsgBody.has("contentType")) {
                        contentType = extractedMsgBody.path("contentType").asText();
                    }
                    // No need to go further if no examples.
                    if (extractedMsgBody.has("examples")) {
                        Iterator<JsonNode> examples = extractedMsgBody.path("examples").elements();
                        int exampleIndex = 0;
                        while (examples.hasNext()) {
                            JsonNode exampleNode = examples.next();
                            EventMessage eventMessage = null;
                            if (exampleNode.has("name")) {
                                // As of AsyncAPI 2.1.0 () we can now have a 'name' property for examples!
                                eventMessage = extractFromAsyncAPI21Example(contentType, exampleNode);
                            } else if (exampleNode.has("payload")) {
                                // As of https://github.com/microcks/microcks/issues/385, we should support the restriction
                                // coming from AsyncAPI GItHub master revision and associated tooling...
                                eventMessage = extractFromAsyncAPIExample(contentType, exampleNode, channelName.trim() + "-" + exampleIndex);
                            } else {
                                eventMessage = extractFromMicrocksExample(contentType, exampleNode);
                            }
                            // add this event message as a valid event in results exchanges.
                            if (eventMessage != null) {
                                if (DispatchStyles.URI_PARTS.equals(operation.getDispatcher())) {
                                    String resourcePathPattern = channelName;
                                    Map<String, String> parts = pathParametersByExample.get(eventMessage.getName());
                                    String resourcePath = URIBuilder.buildURIFromPattern(resourcePathPattern, parts);
                                    operation.addResourcePath(resourcePath);
                                    eventMessage.setDispatchCriteria(DispatchCriteriaHelper.buildFromPartsMap(parts));
                                }
                                result.add(new UnidirectionalEvent(eventMessage));
                            }
                            exampleIndex++;
                        }
                    }
                }
            }
        }
    }
    return result;
}
Also used : ArrayList(java.util.ArrayList) UnidirectionalEvent(io.github.microcks.domain.UnidirectionalEvent) JsonNode(com.fasterxml.jackson.databind.JsonNode) Exchange(io.github.microcks.domain.Exchange) Entry(java.util.Map.Entry) EventMessage(io.github.microcks.domain.EventMessage) HashMap(java.util.HashMap) Map(java.util.Map)

Example 4 with UnidirectionalEvent

use of io.github.microcks.domain.UnidirectionalEvent in project microcks by microcks.

the class AsyncMockDefinitionUpdater method onServiceUpdate.

@Incoming("microcks-services-updates")
public void onServiceUpdate(ServiceViewChangeEvent serviceViewChangeEvent) {
    logger.info("Received a new change event [" + serviceViewChangeEvent.getChangeType() + "] for '" + serviceViewChangeEvent.getServiceId() + "', at " + serviceViewChangeEvent.getTimestamp());
    // Remove existing definitions or add/update existing for EVENT services.
    if (serviceViewChangeEvent.getChangeType().equals(ChangeType.DELETED)) {
        logger.info("Removing mock definitions for " + serviceViewChangeEvent.getServiceId());
        mockRepository.removeMockDefinitions(serviceViewChangeEvent.getServiceId());
        schemaRegistry.clearRegistryForService(serviceViewChangeEvent.getServiceId());
    } else {
        // Only deal with service of type EVENT...
        if (serviceViewChangeEvent.getServiceView() != null && serviceViewChangeEvent.getServiceView().getService().getType().equals(ServiceType.EVENT)) {
            // Browse and check operation regarding restricted frequencies and supported bindings.
            boolean scheduled = false;
            for (Operation operation : serviceViewChangeEvent.getServiceView().getService().getOperations()) {
                if (Arrays.asList(restrictedFrequencies).contains(operation.getDefaultDelay()) && operation.getBindings().keySet().stream().anyMatch(Arrays.asList(supportedBindings)::contains)) {
                    logger.info("Found '" + operation.getName() + "' as a candidate for async message mocking");
                    // Build an Async mock definition and store it into repository.
                    AsyncMockDefinition mockDefinition = new AsyncMockDefinition(serviceViewChangeEvent.getServiceView().getService(), operation, serviceViewChangeEvent.getServiceView().getMessagesMap().get(operation.getName()).stream().filter(e -> e instanceof UnidirectionalEvent).map(e -> ((UnidirectionalEvent) e).getEventMessage()).collect(Collectors.toList()));
                    mockRepository.storeMockDefinition(mockDefinition);
                    schemaRegistry.updateRegistryForService(mockDefinition.getOwnerService());
                    scheduled = true;
                }
            }
            if (!scheduled) {
                logger.info("Ensure to un-schedule " + serviceViewChangeEvent.getServiceId() + " on this minion. Removing definitions.");
                mockRepository.removeMockDefinitions(serviceViewChangeEvent.getServiceId());
                schemaRegistry.clearRegistryForService(serviceViewChangeEvent.getServiceId());
            }
        }
    }
}
Also used : Inject(javax.inject.Inject) Arrays(java.util.Arrays) Operation(io.github.microcks.domain.Operation) ServiceType(io.github.microcks.domain.ServiceType) ChangeType(io.github.microcks.event.ChangeType) Logger(org.jboss.logging.Logger) ApplicationScoped(javax.enterprise.context.ApplicationScoped) ConfigProperty(org.eclipse.microprofile.config.inject.ConfigProperty) UnidirectionalEvent(io.github.microcks.domain.UnidirectionalEvent) Collectors(java.util.stream.Collectors) ServiceViewChangeEvent(io.github.microcks.event.ServiceViewChangeEvent) Incoming(org.eclipse.microprofile.reactive.messaging.Incoming) UnidirectionalEvent(io.github.microcks.domain.UnidirectionalEvent) Operation(io.github.microcks.domain.Operation) Incoming(org.eclipse.microprofile.reactive.messaging.Incoming)

Example 5 with UnidirectionalEvent

use of io.github.microcks.domain.UnidirectionalEvent in project microcks by microcks.

the class ServiceController method getService.

@RequestMapping(value = "/services/{id:.+}", method = RequestMethod.GET)
public ResponseEntity<?> getService(@PathVariable("id") String serviceId, @RequestParam(value = "messages", required = false, defaultValue = "true") boolean messages) {
    log.debug("Retrieving service with id {}", serviceId);
    Service service = null;
    // serviceId may have the form of <service_name>:<service_version>
    if (serviceId.contains(":")) {
        String name = serviceId.substring(0, serviceId.indexOf(':'));
        String version = serviceId.substring(serviceId.indexOf(':') + 1);
        // If service name was encoded with '+' instead of '%20', replace them.
        if (name.contains("+")) {
            name = name.replace('+', ' ');
        }
        service = serviceRepository.findByNameAndVersion(name, version);
    } else {
        service = serviceRepository.findById(serviceId).orElse(null);
    }
    if (messages) {
        // Put messages into a map where key is operation name.
        Map<String, List<? extends Exchange>> messagesMap = new HashMap<>();
        for (Operation operation : service.getOperations()) {
            if (service.getType() == ServiceType.EVENT) {
                // If an event, we should explicitly retrieve event messages.
                List<UnidirectionalEvent> events = messageService.getEventByOperation(IdBuilder.buildOperationId(service, operation));
                messagesMap.put(operation.getName(), events);
            } else {
                // Otherwise we have traditional request / response pairs.
                List<RequestResponsePair> pairs = messageService.getRequestResponseByOperation(IdBuilder.buildOperationId(service, operation));
                messagesMap.put(operation.getName(), pairs);
            }
        }
        return new ResponseEntity<>(new ServiceView(service, messagesMap), HttpStatus.OK);
    }
    return new ResponseEntity<>(service, HttpStatus.OK);
}
Also used : RequestResponsePair(io.github.microcks.domain.RequestResponsePair) ServiceView(io.github.microcks.domain.ServiceView) HashMap(java.util.HashMap) UnidirectionalEvent(io.github.microcks.domain.UnidirectionalEvent) MessageService(io.github.microcks.service.MessageService) ServiceService(io.github.microcks.service.ServiceService) Service(io.github.microcks.domain.Service) Operation(io.github.microcks.domain.Operation) Exchange(io.github.microcks.domain.Exchange) ResponseEntity(org.springframework.http.ResponseEntity) List(java.util.List)

Aggregations

UnidirectionalEvent (io.github.microcks.domain.UnidirectionalEvent)6 Operation (io.github.microcks.domain.Operation)5 Exchange (io.github.microcks.domain.Exchange)4 Service (io.github.microcks.domain.Service)4 RequestResponsePair (io.github.microcks.domain.RequestResponsePair)3 ServiceView (io.github.microcks.domain.ServiceView)3 HashMap (java.util.HashMap)3 List (java.util.List)3 ServiceType (io.github.microcks.domain.ServiceType)2 ServiceViewChangeEvent (io.github.microcks.event.ServiceViewChangeEvent)2 MessageService (io.github.microcks.service.MessageService)2 IOException (java.io.IOException)2 Arrays (java.util.Arrays)2 Collectors (java.util.stream.Collectors)2 ApplicationScoped (javax.enterprise.context.ApplicationScoped)2 Inject (javax.inject.Inject)2 ConfigProperty (org.eclipse.microprofile.config.inject.ConfigProperty)2 Logger (org.jboss.logging.Logger)2 JsonNode (com.fasterxml.jackson.databind.JsonNode)1 EventMessage (io.github.microcks.domain.EventMessage)1