Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package io.openaev.api.xtm_composer;

import io.openaev.aop.RBAC;
import io.openaev.api.xtm_composer.dto.XtmComposerInstanceOutput;
import io.openaev.api.xtm_composer.dto.XtmComposerOutput;
import io.openaev.api.xtm_composer.dto.XtmComposerRegisterInput;
import io.openaev.api.xtm_composer.dto.XtmComposerUpdateStatusInput;
import io.openaev.database.model.Action;
import io.openaev.database.model.ResourceType;
import io.openaev.rest.helper.RestBehavior;
import io.openaev.service.XtmComposerConnectorOrchestrationService;
import io.openaev.service.XtmComposerService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import java.time.LocalDateTime;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
@Tag(name = "XTM COMPOSER API", description = "Operations related to XTM Composer")
public class XtmComposerApi extends RestBehavior {
private static final String XTMCOMPOSER_URI = "/api/xtm-composer";

private final XtmComposerService xtmComposerService;
private final XtmComposerConnectorOrchestrationService orchestrationService;

@PostMapping(value = XTMCOMPOSER_URI + "/register")
@Operation(
summary = "Register XtmComposer",
description = "Save registration data into settings from XTM Composer registration")
@ApiResponses({@ApiResponse(responseCode = "200", description = "Successful registration")})
@RBAC(actionPerformed = Action.WRITE, resourceType = ResourceType.PLATFORM_SETTING)
@Transactional(rollbackFor = Exception.class)
public XtmComposerOutput register(@Valid @RequestBody XtmComposerRegisterInput input) {
return this.xtmComposerService.register(input);
}

@PutMapping(value = XTMCOMPOSER_URI + "/refresh-connectivity")
@Operation(
summary = "Refresh connectivity with XTM composer",
description = "Refresh last check connectivity in settings and version in XTM Composer")
@RBAC(actionPerformed = Action.WRITE, resourceType = ResourceType.PLATFORM_SETTING)
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Successful refresh")})
@Transactional(rollbackFor = Exception.class)
public XtmComposerOutput refreshConnectivity(@Valid @RequestBody String composerId) {
return xtmComposerService.refreshConnectivity(composerId, LocalDateTime.now());
}

@GetMapping(value = XTMCOMPOSER_URI + "/{xtmComposerId}/connector-instances")
@Operation(
summary = "Get all connector instances managed by xtm-composer",
description = "Retrieve all connector instances managed by xtm-composer")
@RBAC(actionPerformed = Action.READ, resourceType = ResourceType.PLATFORM_SETTING)
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Successful retrieval")})
public List<XtmComposerInstanceOutput> getAllConnectorInstances(
@PathVariable @NotBlank final String xtmComposerId) {
return orchestrationService.findConnectorInstancesManagedByComposer(xtmComposerId);
}

@PutMapping(
value = XTMCOMPOSER_URI + "/{xtmComposerId}/connector-instances/{connectorInstanceId}/status")
@Operation(
summary = "Update connector instance status",
description = "Update the status of a specific connector instance")
@RBAC(actionPerformed = Action.WRITE, resourceType = ResourceType.PLATFORM_SETTING)
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Successful update")})
public XtmComposerInstanceOutput updateConnectorInstanceStatus(
@PathVariable @NotBlank final String xtmComposerId,
@PathVariable @NotBlank final String connectorInstanceId,
@Valid @RequestBody XtmComposerUpdateStatusInput input) {
return orchestrationService.updateConnectorInstanceStatus(
xtmComposerId, connectorInstanceId, input.getCurrentStatus());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package io.openaev.api.xtm_composer.dto;

import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.openaev.database.model.ConnectorInstance;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import java.util.List;
import lombok.Builder;
import lombok.Data;

@Data
@Builder
@JsonInclude(NON_NULL)
public class XtmComposerInstanceOutput {
@Builder
@Data
public static class Configuration {
@Schema(description = "Configuration key")
@JsonProperty("configuration_key")
@NotBlank
private String key;

@Schema(description = "Configuration value")
@JsonProperty("configuration_value")
private String value;

@Schema(description = "Configuration value")
@JsonProperty("configuration_is_encrypted")
private boolean isEncrypted;
}

@Schema(description = "Connector Instance Id")
@JsonProperty("connector_instance_id")
@NotBlank
private String id;

@Schema(description = "Connector Instance name")
@JsonProperty("connector_instance_name")
@NotBlank
private String name;

@Schema(description = "Connector Instance hash")
@JsonProperty("connector_instance_hash")
@NotBlank
private String hash;

@Schema(description = "Connector image")
@JsonProperty("connector_image")
@NotBlank
private String image;

@Schema(description = "Connector Instance current status")
@JsonProperty("connector_instance_current_status")
@NotBlank
private ConnectorInstance.CURRENT_STATUS_TYPE currentStatus;

@Schema(description = "Connector Instance requested status")
@JsonProperty("connector_instance_requested_status")
@NotBlank
private ConnectorInstance.REQUESTED_STATUS_TYPE requestedStatus;

@Schema(description = "Connector Instance configuration")
@JsonProperty("connector_instance_configuration")
@NotBlank
private List<Configuration> configuration;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package io.openaev.api.xtm_composer.dto;

import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Builder;
import lombok.Data;

@Data
@Builder
@JsonInclude(NON_NULL)
public class XtmComposerOutput {
@Schema(description = "XTM Composer Id")
@JsonProperty("xtm_composer_id")
@NotBlank
private String id;

@Schema(description = "XTM Composer Version")
@JsonProperty("xtm_composer_version")
@NotBlank
private String version;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.openaev.api.xtm_composer.dto;

import static io.openaev.config.AppConfig.MANDATORY_MESSAGE;

import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class XtmComposerRegisterInput {
@NotBlank(message = MANDATORY_MESSAGE)
@Schema(description = "The XTM Composer Id")
private String id;

@NotBlank(message = MANDATORY_MESSAGE)
@Schema(description = "The XTM Composer Name")
private String name;

@NotBlank(message = MANDATORY_MESSAGE)
@Schema(description = "The registration public key")
@JsonProperty("public_key")
private String publicKey;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.openaev.api.xtm_composer.dto;

import static io.openaev.config.AppConfig.MANDATORY_MESSAGE;

import com.fasterxml.jackson.annotation.JsonProperty;
import io.openaev.database.model.ConnectorInstance;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Getter;

@Getter
public class XtmComposerUpdateStatusInput {
@NotNull(message = MANDATORY_MESSAGE)
@Schema(description = "The connector instance current status")
@JsonProperty("connector_instance_current_status")
private ConnectorInstance.CURRENT_STATUS_TYPE currentStatus;
}
Original file line number Diff line number Diff line change
@@ -1,31 +1,113 @@
package io.openaev.executors;

import static io.openaev.helper.StreamHelper.fromIterable;
import static io.openaev.service.FileService.*;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.openaev.database.model.*;
import io.openaev.database.model.Executor;
import io.openaev.database.repository.ConnectorInstanceConfigurationRepository;
import io.openaev.database.repository.ExecutionTraceRepository;
import io.openaev.database.repository.ExecutorRepository;
import io.openaev.rest.catalog_connector.dto.ConnectorIds;
import io.openaev.rest.executor.form.ExecutorOutput;
import io.openaev.service.ConnectorInstanceService;
import io.openaev.service.FileService;
import io.openaev.service.catalog_connectors.CatalogConnectorService;
import io.openaev.service.connectors.AbstractConnectorService;
import io.openaev.utils.mapper.CatalogConnectorMapper;
import io.openaev.utils.mapper.ExecutorMapper;
import jakarta.annotation.Resource;
import jakarta.transaction.Transactional;
import java.io.InputStream;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class ExecutorService {
public class ExecutorService extends AbstractConnectorService<Executor, ExecutorOutput> {

public static final String EXT_PNG = ".png";
@Resource protected ObjectMapper mapper;

private final FileService fileService;
private final ExecutorRepository executorRepository;
private final ExecutionTraceRepository executionTraceRepository;

private final FileService fileService;
private final ConnectorInstanceService connectorInstanceService;

private final ExecutorMapper executorMapper;

@Autowired
public ExecutorService(
ExecutorRepository executorRepository,
ConnectorInstanceConfigurationRepository connectorInstanceConfigurationRepository,
ExecutionTraceRepository executionTraceRepository,
FileService fileService,
CatalogConnectorService catalogConnectorService,
ConnectorInstanceService connectorInstanceService,
ExecutorMapper executorMapper,
CatalogConnectorMapper catalogConnectorMapper) {
super(
connectorInstanceConfigurationRepository, catalogConnectorService, catalogConnectorMapper);
this.fileService = fileService;
this.executorRepository = executorRepository;
this.executionTraceRepository = executionTraceRepository;
this.connectorInstanceService = connectorInstanceService;
this.executorMapper = executorMapper;
}

@Override
protected String getConfigurationKey() {
return "EXECUTOR_ID";
}

@Override
protected List<ConnectorInstance> getRelatedInstances() {
return connectorInstanceService.executorConnectorInstances();
}

@Override
protected List<Executor> getAllConnectors() {
return fromIterable(this.executors());
}

@Override
protected Executor getConnectorById(String executorId) {
return executorRepository.findById(executorId).orElse(null);
}

@Override
protected ExecutorOutput mapToOutput(
Executor executor, CatalogConnector catalogConnector, boolean isVerified) {
return executorMapper.toExecutorOutput(executor, catalogConnector, isVerified);
}

@Override
protected Executor createNewConnector() {
return new Executor();
}

/**
* Retrieve all executors.
*
* @param isIncludeNext Include pending executors.
* @return List of executor output
*/
public Iterable<ExecutorOutput> executorsOutput(boolean isIncludeNext) {
return getConnectorsOutput(isIncludeNext);
}

/**
* Retrieves IDs of resources associated with an executor.
*
* @param executorId executor identifier.
* @return connector instance ID and catalog connector ID if available, null values if not found
*/
public ConnectorIds getExecutorRelationsId(String executorId) {
return getConnectorRelationsId(executorId);
}

public Iterable<Executor> executors() {
return this.executorRepository.findAll();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,37 @@
package io.openaev.migration;

import java.sql.Statement;
import org.flywaydb.core.api.migration.BaseJavaMigration;
import org.flywaydb.core.api.migration.Context;
import org.springframework.stereotype.Component;

import java.sql.Statement;

@Component
public class V4_53__Update_catalog_connector_configuration_type extends BaseJavaMigration {
@Override
public void migrate(Context context) throws Exception {
try (Statement select = context.getConnection().createStatement()) {
select.execute(
"""
@Override
public void migrate(Context context) throws Exception {
try (Statement select = context.getConnection().createStatement()) {
select.execute(
"""
CREATE TYPE connector_configuration_type AS ENUM ('ARRAY', 'BOOLEAN', 'INTEGER', 'OBJECT', 'STRING');
CREATE TYPE connector_configuration_format AS ENUM ('DATE', 'DATETIME', 'DURATION', 'EMAIL', 'PASSWORD', 'URI');

ALTER TABLE catalog_connectors_configuration
DROP COLUMN IF EXISTS connector_configuration_type,
DROP COLUMN IF EXISTS connector_configuration_format
""");

select.execute(
"""
select.execute(
"""
ALTER TABLE catalog_connectors_configuration
ADD COLUMN connector_configuration_type connector_configuration_type,
ADD COLUMN connector_configuration_format connector_configuration_format
""");

select.execute(
"""
select.execute(
"""
ALTER TABLE connector_instance_logs
RENAME COLUMN connector_configuration_created_at TO connector_instance_log_created_at;
""");
}
}
}
}
Loading
Loading