mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-12-02 18:46:02 +00:00
GEN-1322: API Entity - Remove Beta (#17967)
* GEN-1322: API Entity - Remove Beta * minor: add doc for the metadata pipeline * api service refactor * api service refactor backend changes * add apiconnection in test service connection * pytest fix * fix java file formatting * Fix casing of REST in ApiServiceRest.spec.ts * Refactor REST to Rest in API classes * minor change * minor change * minor change * fix cashing for API to Api * add playwright test for api service ingestion * fix: playwright test --------- Co-authored-by: harshsoni2024 <harshsoni2024@gmail.com>
This commit is contained in:
parent
53cdd34391
commit
457f3d919a
@ -1,9 +1,9 @@
|
||||
{
|
||||
"type": "REST",
|
||||
"type": "rest",
|
||||
"serviceName": "sample_api_service",
|
||||
"serviceConnection": {
|
||||
"config": {
|
||||
"type": "REST",
|
||||
"type": "Rest",
|
||||
"openAPISchemaURL": "https://petstore3.swagger.io/",
|
||||
"token":"mock_token"
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
{
|
||||
"type": "REST",
|
||||
"type": "rest",
|
||||
"serviceName": "ometa_api_service",
|
||||
"serviceConnection": {
|
||||
"config": {
|
||||
"type": "REST",
|
||||
"type": "Rest",
|
||||
"openAPISchemaURL": "https://docs.open-metadata.org/swagger.html",
|
||||
"token":"token"
|
||||
}
|
||||
|
||||
@ -3,9 +3,9 @@ source:
|
||||
serviceName: openapi_rest
|
||||
serviceConnection:
|
||||
config:
|
||||
type: REST
|
||||
type: Rest
|
||||
openAPISchemaURL: https://docs.open-metadata.org/swagger.json
|
||||
token: <optional_jwt_token>
|
||||
# token: <jwt_token>
|
||||
sourceConfig:
|
||||
config:
|
||||
type: ApiMetadata
|
||||
|
||||
@ -19,8 +19,8 @@ from metadata.generated.schema.entity.automations.workflow import (
|
||||
Workflow as AutomationWorkflow,
|
||||
)
|
||||
from metadata.generated.schema.entity.services.apiService import (
|
||||
ApiServiceConnection,
|
||||
APIServiceType,
|
||||
ApiConnection,
|
||||
ApiServiceType,
|
||||
)
|
||||
from metadata.generated.schema.entity.services.dashboardService import (
|
||||
DashboardConnection,
|
||||
@ -135,7 +135,7 @@ HAS_INNER_CONNECTION = {"Airflow"}
|
||||
# Build a service type map dynamically from JSON Schema covered types
|
||||
SERVICE_TYPE_MAP = {
|
||||
"Backend": PipelineConnection, # For Airflow backend
|
||||
**{service: ApiServiceConnection for service in APIServiceType.__members__},
|
||||
**{service: ApiConnection for service in ApiServiceType.__members__},
|
||||
**{service: DatabaseConnection for service in DatabaseServiceType.__members__},
|
||||
**{service: DashboardConnection for service in DashboardServiceType.__members__},
|
||||
**{service: MessagingConnection for service in MessagingServiceType.__members__},
|
||||
@ -183,7 +183,7 @@ class InvalidWorkflowException(Exception):
|
||||
def get_service_type(
|
||||
source_type: str,
|
||||
) -> Union[
|
||||
Type[ApiServiceConnection],
|
||||
Type[ApiConnection],
|
||||
Type[DashboardConnection],
|
||||
Type[DatabaseConnection],
|
||||
Type[MessagingConnection],
|
||||
@ -233,7 +233,7 @@ def get_source_config_class(
|
||||
def get_connection_class(
|
||||
source_type: str,
|
||||
service_type: Union[
|
||||
Type[ApiServiceConnection],
|
||||
Type[ApiConnection],
|
||||
Type[DashboardConnection],
|
||||
Type[DatabaseConnection],
|
||||
Type[MessagingConnection],
|
||||
@ -557,6 +557,7 @@ def parse_automation_workflow_gracefully(
|
||||
message="Error parsing the service connection",
|
||||
)
|
||||
|
||||
#
|
||||
raise ParsingConfigurationError(
|
||||
"Uncaught error when parsing the Ingestion Pipeline!"
|
||||
)
|
||||
|
||||
@ -26,8 +26,8 @@ from metadata.generated.schema.api.data.createAPIEndpoint import (
|
||||
from metadata.generated.schema.entity.data.apiCollection import APICollection
|
||||
from metadata.generated.schema.entity.data.apiEndpoint import APIEndpoint
|
||||
from metadata.generated.schema.entity.services.apiService import (
|
||||
ApiConnection,
|
||||
ApiService,
|
||||
ApiServiceConnection,
|
||||
)
|
||||
from metadata.generated.schema.metadataIngestion.apiServiceMetadataPipeline import (
|
||||
ApiServiceMetadataPipeline,
|
||||
@ -112,7 +112,7 @@ class ApiServiceSource(TopologyRunnerMixin, Source, ABC):
|
||||
source_config: ApiServiceMetadataPipeline
|
||||
config: WorkflowSource
|
||||
# Big union of types we want to fetch dynamically
|
||||
service_connection: ApiServiceConnection.model_fields["config"].annotation
|
||||
service_connection: ApiConnection.model_fields["config"].annotation
|
||||
|
||||
topology = ApiServiceTopology()
|
||||
context = TopologyContextManager(topology)
|
||||
|
||||
@ -20,8 +20,8 @@ from requests.models import Response
|
||||
from metadata.generated.schema.entity.automations.workflow import (
|
||||
Workflow as AutomationWorkflow,
|
||||
)
|
||||
from metadata.generated.schema.entity.services.connections.apiService.restConnection import (
|
||||
RESTConnection,
|
||||
from metadata.generated.schema.entity.services.connections.api.restConnection import (
|
||||
RestConnection,
|
||||
)
|
||||
from metadata.ingestion.connections.test_connections import test_connection_steps
|
||||
from metadata.ingestion.ometa.ometa_api import OpenMetadata
|
||||
@ -39,7 +39,7 @@ class InvalidOpenAPISchemaError(Exception):
|
||||
"""
|
||||
|
||||
|
||||
def get_connection(connection: RESTConnection) -> Response:
|
||||
def get_connection(connection: RestConnection) -> Response:
|
||||
"""
|
||||
Create connection
|
||||
"""
|
||||
@ -52,7 +52,7 @@ def get_connection(connection: RESTConnection) -> Response:
|
||||
def test_connection(
|
||||
metadata: OpenMetadata,
|
||||
client: Response,
|
||||
service_connection: RESTConnection,
|
||||
service_connection: RestConnection,
|
||||
automation_workflow: Optional[AutomationWorkflow] = None,
|
||||
) -> None:
|
||||
"""
|
||||
|
||||
@ -23,8 +23,8 @@ from metadata.generated.schema.api.data.createAPIEndpoint import (
|
||||
)
|
||||
from metadata.generated.schema.entity.data.apiCollection import APICollection
|
||||
from metadata.generated.schema.entity.data.apiEndpoint import ApiRequestMethod
|
||||
from metadata.generated.schema.entity.services.connections.apiService.restConnection import (
|
||||
RESTConnection,
|
||||
from metadata.generated.schema.entity.services.connections.api.restConnection import (
|
||||
RestConnection,
|
||||
)
|
||||
from metadata.generated.schema.entity.services.ingestionPipelines.status import (
|
||||
StackTraceError,
|
||||
@ -62,10 +62,10 @@ class RestSource(ApiServiceSource):
|
||||
cls, config_dict, metadata: OpenMetadata, pipeline_name: Optional[str] = None
|
||||
):
|
||||
config: WorkflowSource = WorkflowSource.model_validate(config_dict)
|
||||
connection: RESTConnection = config.serviceConnection.root.config
|
||||
if not isinstance(connection, RESTConnection):
|
||||
connection: RestConnection = config.serviceConnection.root.config
|
||||
if not isinstance(connection, RestConnection):
|
||||
raise InvalidSourceException(
|
||||
f"Expected RESTConnection, but got {connection}"
|
||||
f"Expected RestConnection, but got {connection}"
|
||||
)
|
||||
return cls(config, metadata)
|
||||
|
||||
|
||||
@ -68,7 +68,7 @@ from metadata.generated.schema.metadataIngestion.testSuitePipeline import (
|
||||
from metadata.generated.schema.metadataIngestion.workflow import SourceConfig
|
||||
|
||||
SERVICE_TYPE_REF = {
|
||||
ServiceType.API.value: "apiService",
|
||||
ServiceType.Api.value: "apiService",
|
||||
ServiceType.Database.value: "databaseService",
|
||||
ServiceType.Dashboard.value: "dashboardService",
|
||||
ServiceType.Pipeline.value: "pipelineService",
|
||||
|
||||
@ -19,6 +19,9 @@ from pydantic import ValidationError
|
||||
from metadata.generated.schema.entity.automations.workflow import (
|
||||
Workflow as AutomationWorkflow,
|
||||
)
|
||||
from metadata.generated.schema.entity.services.connections.api.restConnection import (
|
||||
RestConnection,
|
||||
)
|
||||
from metadata.generated.schema.entity.services.connections.dashboard.tableauConnection import (
|
||||
TableauConnection,
|
||||
)
|
||||
@ -115,6 +118,10 @@ class TestWorkflowParse(TestCase):
|
||||
connection = get_connection_class(source_type, get_service_type(source_type))
|
||||
self.assertEqual(connection, KafkaConnection)
|
||||
|
||||
source_type = "Rest"
|
||||
connection = get_connection_class(source_type, get_service_type(source_type))
|
||||
self.assertEqual(connection, RestConnection)
|
||||
|
||||
def test_get_source_config_class(self):
|
||||
"""
|
||||
Check that we can correctly build the connection module ingredients
|
||||
|
||||
@ -21,9 +21,9 @@ from metadata.generated.schema.api.data.createAPICollection import (
|
||||
CreateAPICollectionRequest,
|
||||
)
|
||||
from metadata.generated.schema.entity.services.apiService import (
|
||||
ApiConnection,
|
||||
ApiService,
|
||||
ApiServiceConnection,
|
||||
APIServiceType,
|
||||
ApiServiceType,
|
||||
)
|
||||
from metadata.generated.schema.metadataIngestion.workflow import (
|
||||
OpenMetadataWorkflowConfig,
|
||||
@ -43,7 +43,7 @@ mock_rest_config = {
|
||||
"serviceName": "openapi_rest",
|
||||
"serviceConnection": {
|
||||
"config": {
|
||||
"type": "REST",
|
||||
"type": "Rest",
|
||||
"openAPISchemaURL": "https://petstore3.swagger.io/api/v3/openapi.json",
|
||||
}
|
||||
},
|
||||
@ -91,8 +91,8 @@ MOCK_API_SERVICE = ApiService(
|
||||
id="c3eb265f-5445-4ad3-ba5e-797d3a3071bb",
|
||||
name="openapi_rest",
|
||||
fullyQualifiedName=FullyQualifiedEntityName("openapi_rest"),
|
||||
connection=ApiServiceConnection(),
|
||||
serviceType=APIServiceType.REST,
|
||||
connection=ApiConnection(),
|
||||
serviceType=ApiServiceType.Rest,
|
||||
)
|
||||
EXPECTED_COLLECTION_REQUEST = [
|
||||
Either(
|
||||
|
||||
@ -18,7 +18,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.jdbi.v3.sqlobject.transaction.Transaction;
|
||||
import org.openmetadata.schema.EntityInterface;
|
||||
import org.openmetadata.schema.entity.data.APICollection;
|
||||
import org.openmetadata.schema.entity.services.APIService;
|
||||
import org.openmetadata.schema.entity.services.ApiService;
|
||||
import org.openmetadata.schema.type.EntityReference;
|
||||
import org.openmetadata.schema.type.Include;
|
||||
import org.openmetadata.schema.type.Relationship;
|
||||
@ -108,7 +108,7 @@ public class APICollectionRepository extends EntityRepository<APICollection> {
|
||||
}
|
||||
|
||||
private void populateService(APICollection apiCollection) {
|
||||
APIService service = Entity.getEntity(apiCollection.getService(), "", Include.NON_DELETED);
|
||||
ApiService service = Entity.getEntity(apiCollection.getService(), "", Include.NON_DELETED);
|
||||
apiCollection.setService(service.getEntityReference());
|
||||
apiCollection.setServiceType(service.getServiceType());
|
||||
}
|
||||
|
||||
@ -1,19 +1,18 @@
|
||||
package org.openmetadata.service.jdbi3;
|
||||
|
||||
import org.openmetadata.schema.entity.services.APIService;
|
||||
import org.openmetadata.schema.entity.services.ApiService;
|
||||
import org.openmetadata.schema.entity.services.ServiceType;
|
||||
import org.openmetadata.schema.type.APIServiceConnection;
|
||||
import org.openmetadata.schema.type.ApiConnection;
|
||||
import org.openmetadata.service.Entity;
|
||||
import org.openmetadata.service.resources.services.apiservices.APIServiceResource;
|
||||
|
||||
public class APIServiceRepository
|
||||
extends ServiceEntityRepository<APIService, APIServiceConnection> {
|
||||
public class APIServiceRepository extends ServiceEntityRepository<ApiService, ApiConnection> {
|
||||
public APIServiceRepository() {
|
||||
super(
|
||||
APIServiceResource.COLLECTION_PATH,
|
||||
Entity.API_SERVICE,
|
||||
Entity.getCollectionDAO().apiServiceDAO(),
|
||||
APIServiceConnection.class,
|
||||
ApiConnection.class,
|
||||
"",
|
||||
ServiceType.API);
|
||||
supportsSearch = true;
|
||||
|
||||
@ -98,7 +98,7 @@ import org.openmetadata.schema.entity.domains.DataProduct;
|
||||
import org.openmetadata.schema.entity.domains.Domain;
|
||||
import org.openmetadata.schema.entity.events.EventSubscription;
|
||||
import org.openmetadata.schema.entity.policies.Policy;
|
||||
import org.openmetadata.schema.entity.services.APIService;
|
||||
import org.openmetadata.schema.entity.services.ApiService;
|
||||
import org.openmetadata.schema.entity.services.DashboardService;
|
||||
import org.openmetadata.schema.entity.services.DatabaseService;
|
||||
import org.openmetadata.schema.entity.services.MessagingService;
|
||||
@ -288,7 +288,7 @@ public interface CollectionDAO {
|
||||
SearchServiceDAO searchServiceDAO();
|
||||
|
||||
@CreateSqlObject
|
||||
APIServiceDAO apiServiceDAO();
|
||||
ApiServiceDAO apiServiceDAO();
|
||||
|
||||
@CreateSqlObject
|
||||
ContainerDAO containerDAO();
|
||||
@ -636,15 +636,15 @@ public interface CollectionDAO {
|
||||
}
|
||||
}
|
||||
|
||||
interface APIServiceDAO extends EntityDAO<APIService> {
|
||||
interface ApiServiceDAO extends EntityDAO<ApiService> {
|
||||
@Override
|
||||
default String getTableName() {
|
||||
return "api_service_entity";
|
||||
}
|
||||
|
||||
@Override
|
||||
default Class<APIService> getEntityClass() {
|
||||
return APIService.class;
|
||||
default Class<ApiService> getEntityClass() {
|
||||
return ApiService.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -47,11 +47,11 @@ import javax.ws.rs.core.SecurityContext;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.openmetadata.schema.api.data.RestoreEntity;
|
||||
import org.openmetadata.schema.api.services.CreateAPIService;
|
||||
import org.openmetadata.schema.entity.services.APIService;
|
||||
import org.openmetadata.schema.api.services.CreateApiService;
|
||||
import org.openmetadata.schema.entity.services.ApiService;
|
||||
import org.openmetadata.schema.entity.services.ServiceType;
|
||||
import org.openmetadata.schema.entity.services.connections.TestConnectionResult;
|
||||
import org.openmetadata.schema.type.APIServiceConnection;
|
||||
import org.openmetadata.schema.type.ApiConnection;
|
||||
import org.openmetadata.schema.type.EntityHistory;
|
||||
import org.openmetadata.schema.type.Include;
|
||||
import org.openmetadata.schema.type.MetadataOperation;
|
||||
@ -75,12 +75,12 @@ import org.openmetadata.service.util.ResultList;
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Collection(name = "apiServices")
|
||||
public class APIServiceResource
|
||||
extends ServiceEntityResource<APIService, APIServiceRepository, APIServiceConnection> {
|
||||
extends ServiceEntityResource<ApiService, APIServiceRepository, ApiConnection> {
|
||||
public static final String COLLECTION_PATH = "v1/services/apiServices/";
|
||||
static final String FIELDS = "pipelines,owners,tags,domain";
|
||||
|
||||
@Override
|
||||
public APIService addHref(UriInfo uriInfo, APIService service) {
|
||||
public ApiService addHref(UriInfo uriInfo, ApiService service) {
|
||||
super.addHref(uriInfo, service);
|
||||
Entity.withHref(uriInfo, service.getPipelines());
|
||||
return service;
|
||||
@ -96,7 +96,7 @@ public class APIServiceResource
|
||||
return null;
|
||||
}
|
||||
|
||||
public static class APIServiceList extends ResultList<APIService> {
|
||||
public static class APIServiceList extends ResultList<ApiService> {
|
||||
/* Required for serde */
|
||||
}
|
||||
|
||||
@ -118,7 +118,7 @@ public class APIServiceResource
|
||||
org.openmetadata.service.resources.services.apiservices
|
||||
.APIServiceResource.APIServiceList.class)))
|
||||
})
|
||||
public ResultList<APIService> list(
|
||||
public ResultList<ApiService> list(
|
||||
@Context UriInfo uriInfo,
|
||||
@Context SecurityContext securityContext,
|
||||
@Parameter(
|
||||
@ -165,12 +165,12 @@ public class APIServiceResource
|
||||
content =
|
||||
@Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = APIService.class))),
|
||||
schema = @Schema(implementation = ApiService.class))),
|
||||
@ApiResponse(
|
||||
responseCode = "404",
|
||||
description = "API service for instance {id} is not found")
|
||||
})
|
||||
public APIService get(
|
||||
public ApiService get(
|
||||
@Context UriInfo uriInfo,
|
||||
@Context SecurityContext securityContext,
|
||||
@PathParam("id") UUID id,
|
||||
@ -185,7 +185,7 @@ public class APIServiceResource
|
||||
@QueryParam("include")
|
||||
@DefaultValue("non-deleted")
|
||||
Include include) {
|
||||
APIService apiService = getInternal(uriInfo, securityContext, id, fieldsParam, include);
|
||||
ApiService apiService = getInternal(uriInfo, securityContext, id, fieldsParam, include);
|
||||
return decryptOrNullify(securityContext, apiService);
|
||||
}
|
||||
|
||||
@ -202,12 +202,12 @@ public class APIServiceResource
|
||||
content =
|
||||
@Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = APIService.class))),
|
||||
schema = @Schema(implementation = ApiService.class))),
|
||||
@ApiResponse(
|
||||
responseCode = "404",
|
||||
description = "API service for instance {id} is not found")
|
||||
})
|
||||
public APIService getByName(
|
||||
public ApiService getByName(
|
||||
@Context UriInfo uriInfo,
|
||||
@Context SecurityContext securityContext,
|
||||
@PathParam("name") String name,
|
||||
@ -222,7 +222,7 @@ public class APIServiceResource
|
||||
@QueryParam("include")
|
||||
@DefaultValue("non-deleted")
|
||||
Include include) {
|
||||
APIService apiService =
|
||||
ApiService apiService =
|
||||
getByNameInternal(
|
||||
uriInfo, securityContext, EntityInterfaceUtil.quoteName(name), fieldsParam, include);
|
||||
return decryptOrNullify(securityContext, apiService);
|
||||
@ -241,9 +241,9 @@ public class APIServiceResource
|
||||
content =
|
||||
@Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = APIService.class)))
|
||||
schema = @Schema(implementation = ApiService.class)))
|
||||
})
|
||||
public APIService addTestConnectionResult(
|
||||
public ApiService addTestConnectionResult(
|
||||
@Context UriInfo uriInfo,
|
||||
@Context SecurityContext securityContext,
|
||||
@Parameter(description = "Id of the service", schema = @Schema(type = "UUID"))
|
||||
@ -252,7 +252,7 @@ public class APIServiceResource
|
||||
@Valid TestConnectionResult testConnectionResult) {
|
||||
OperationContext operationContext = new OperationContext(entityType, MetadataOperation.CREATE);
|
||||
authorizer.authorize(securityContext, operationContext, getResourceContextById(id));
|
||||
APIService service = repository.addTestConnectionResult(id, testConnectionResult);
|
||||
ApiService service = repository.addTestConnectionResult(id, testConnectionResult);
|
||||
return decryptOrNullify(securityContext, service);
|
||||
}
|
||||
|
||||
@ -283,7 +283,7 @@ public class APIServiceResource
|
||||
.map(
|
||||
json -> {
|
||||
try {
|
||||
APIService apiService = JsonUtils.readValue((String) json, APIService.class);
|
||||
ApiService apiService = JsonUtils.readValue((String) json, ApiService.class);
|
||||
return JsonUtils.pojoToJson(decryptOrNullify(securityContext, apiService));
|
||||
} catch (Exception e) {
|
||||
return json;
|
||||
@ -307,12 +307,12 @@ public class APIServiceResource
|
||||
content =
|
||||
@Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = APIService.class))),
|
||||
schema = @Schema(implementation = ApiService.class))),
|
||||
@ApiResponse(
|
||||
responseCode = "404",
|
||||
description = "API service for instance {id} and version {version} is not found")
|
||||
})
|
||||
public APIService getVersion(
|
||||
public ApiService getVersion(
|
||||
@Context UriInfo uriInfo,
|
||||
@Context SecurityContext securityContext,
|
||||
@Parameter(description = "API service Id", schema = @Schema(type = "string")) @PathParam("id")
|
||||
@ -322,13 +322,13 @@ public class APIServiceResource
|
||||
schema = @Schema(type = "string", example = "0.1 or 1.1"))
|
||||
@PathParam("version")
|
||||
String version) {
|
||||
APIService apiService = super.getVersionInternal(securityContext, id, version);
|
||||
ApiService apiService = super.getVersionInternal(securityContext, id, version);
|
||||
return decryptOrNullify(securityContext, apiService);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Operation(
|
||||
operationId = "createAPIService",
|
||||
operationId = "createApiService",
|
||||
summary = "Create API service",
|
||||
description = "Create a new API service.",
|
||||
responses = {
|
||||
@ -338,16 +338,16 @@ public class APIServiceResource
|
||||
content =
|
||||
@Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = APIService.class))),
|
||||
schema = @Schema(implementation = ApiService.class))),
|
||||
@ApiResponse(responseCode = "400", description = "Bad request")
|
||||
})
|
||||
public Response create(
|
||||
@Context UriInfo uriInfo,
|
||||
@Context SecurityContext securityContext,
|
||||
@Valid CreateAPIService create) {
|
||||
APIService service = getService(create, securityContext.getUserPrincipal().getName());
|
||||
@Valid CreateApiService create) {
|
||||
ApiService service = getService(create, securityContext.getUserPrincipal().getName());
|
||||
Response response = create(uriInfo, securityContext, service);
|
||||
decryptOrNullify(securityContext, (APIService) response.getEntity());
|
||||
decryptOrNullify(securityContext, (ApiService) response.getEntity());
|
||||
return response;
|
||||
}
|
||||
|
||||
@ -363,16 +363,16 @@ public class APIServiceResource
|
||||
content =
|
||||
@Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = APIService.class))),
|
||||
schema = @Schema(implementation = ApiService.class))),
|
||||
@ApiResponse(responseCode = "400", description = "Bad request")
|
||||
})
|
||||
public Response createOrUpdate(
|
||||
@Context UriInfo uriInfo,
|
||||
@Context SecurityContext securityContext,
|
||||
@Valid CreateAPIService update) {
|
||||
APIService service = getService(update, securityContext.getUserPrincipal().getName());
|
||||
@Valid CreateApiService update) {
|
||||
ApiService service = getService(update, securityContext.getUserPrincipal().getName());
|
||||
Response response = createOrUpdate(uriInfo, securityContext, unmask(service));
|
||||
decryptOrNullify(securityContext, (APIService) response.getEntity());
|
||||
decryptOrNullify(securityContext, (ApiService) response.getEntity());
|
||||
return response;
|
||||
}
|
||||
|
||||
@ -504,7 +504,7 @@ public class APIServiceResource
|
||||
content =
|
||||
@Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = APIService.class)))
|
||||
schema = @Schema(implementation = ApiService.class)))
|
||||
})
|
||||
public Response restoreAPIService(
|
||||
@Context UriInfo uriInfo,
|
||||
@ -513,20 +513,20 @@ public class APIServiceResource
|
||||
return restoreEntity(uriInfo, securityContext, restore.getId());
|
||||
}
|
||||
|
||||
private APIService getService(CreateAPIService create, String user) {
|
||||
private ApiService getService(CreateApiService create, String user) {
|
||||
return repository
|
||||
.copy(new APIService(), create, user)
|
||||
.copy(new ApiService(), create, user)
|
||||
.withServiceType(create.getServiceType())
|
||||
.withConnection(create.getConnection());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected APIService nullifyConnection(APIService service) {
|
||||
protected ApiService nullifyConnection(ApiService service) {
|
||||
return service.withConnection(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String extractServiceType(APIService service) {
|
||||
protected String extractServiceType(ApiService service) {
|
||||
return service.getServiceType().value();
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,15 +23,8 @@ import org.openmetadata.schema.entity.data.Table;
|
||||
import org.openmetadata.schema.entity.data.Topic;
|
||||
import org.openmetadata.schema.entity.domains.DataProduct;
|
||||
import org.openmetadata.schema.entity.domains.Domain;
|
||||
import org.openmetadata.schema.entity.services.APIService;
|
||||
import org.openmetadata.schema.entity.services.DashboardService;
|
||||
import org.openmetadata.schema.entity.services.DatabaseService;
|
||||
import org.openmetadata.schema.entity.services.MessagingService;
|
||||
import org.openmetadata.schema.entity.services.MetadataService;
|
||||
import org.openmetadata.schema.entity.services.MlModelService;
|
||||
import org.openmetadata.schema.entity.services.PipelineService;
|
||||
import org.openmetadata.schema.entity.services.SearchService;
|
||||
import org.openmetadata.schema.entity.services.StorageService;
|
||||
import org.openmetadata.schema.entity.services.*;
|
||||
import org.openmetadata.schema.entity.services.ApiService;
|
||||
import org.openmetadata.schema.entity.services.ingestionPipelines.IngestionPipeline;
|
||||
import org.openmetadata.schema.entity.teams.Team;
|
||||
import org.openmetadata.schema.entity.teams.User;
|
||||
@ -118,7 +111,7 @@ public class SearchIndexFactory {
|
||||
case Entity.MESSAGING_SERVICE -> new MessagingServiceIndex((MessagingService) entity);
|
||||
case Entity.MLMODEL_SERVICE -> new MlModelServiceIndex((MlModelService) entity);
|
||||
case Entity.SEARCH_SERVICE -> new SearchServiceIndex((SearchService) entity);
|
||||
case Entity.API_SERVICE -> new APIServiceIndex((APIService) entity);
|
||||
case Entity.API_SERVICE -> new APIServiceIndex((ApiService) entity);
|
||||
case Entity.SEARCH_INDEX -> new SearchEntityIndex(
|
||||
(org.openmetadata.schema.entity.data.SearchIndex) entity);
|
||||
case Entity.PIPELINE_SERVICE -> new PipelineServiceIndex((PipelineService) entity);
|
||||
|
||||
@ -3,11 +3,11 @@ package org.openmetadata.service.search.indexes;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.openmetadata.schema.entity.services.APIService;
|
||||
import org.openmetadata.service.Entity;
|
||||
import org.openmetadata.service.search.models.SearchSuggest;
|
||||
|
||||
public record APIServiceIndex(APIService apiService) implements SearchIndex {
|
||||
public record APIServiceIndex(org.openmetadata.schema.entity.services.ApiService apiService)
|
||||
implements SearchIndex {
|
||||
|
||||
@Override
|
||||
public List<SearchSuggest> getSuggest() {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "REST",
|
||||
"name": "Rest",
|
||||
"displayName": "REST Test Connection",
|
||||
"description": "This Test Connection validates the schema provided for openapi",
|
||||
"steps": [
|
||||
|
||||
@ -22,23 +22,23 @@ import org.apache.http.client.HttpResponseException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInfo;
|
||||
import org.openmetadata.common.utils.CommonUtil;
|
||||
import org.openmetadata.schema.api.services.CreateAPIService;
|
||||
import org.openmetadata.schema.entity.services.APIService;
|
||||
import org.openmetadata.schema.api.services.CreateApiService;
|
||||
import org.openmetadata.schema.entity.services.ApiService;
|
||||
import org.openmetadata.schema.entity.services.connections.TestConnectionResult;
|
||||
import org.openmetadata.schema.entity.services.connections.TestConnectionResultStatus;
|
||||
import org.openmetadata.schema.services.connections.api.RESTConnection;
|
||||
import org.openmetadata.schema.type.APIServiceConnection;
|
||||
import org.openmetadata.schema.services.connections.api.RestConnection;
|
||||
import org.openmetadata.schema.type.ApiConnection;
|
||||
import org.openmetadata.schema.type.ChangeDescription;
|
||||
import org.openmetadata.service.Entity;
|
||||
import org.openmetadata.service.resources.services.apiservices.APIServiceResource;
|
||||
import org.openmetadata.service.util.JsonUtils;
|
||||
import org.openmetadata.service.util.TestUtils;
|
||||
|
||||
public class APIServiceResourceTest extends ServiceResourceTest<APIService, CreateAPIService> {
|
||||
public class APIServiceResourceTest extends ServiceResourceTest<ApiService, CreateApiService> {
|
||||
public APIServiceResourceTest() {
|
||||
super(
|
||||
Entity.API_SERVICE,
|
||||
APIService.class,
|
||||
ApiService.class,
|
||||
APIServiceResource.APIServiceList.class,
|
||||
"services/apiServices",
|
||||
"owners");
|
||||
@ -47,25 +47,25 @@ public class APIServiceResourceTest extends ServiceResourceTest<APIService, Crea
|
||||
|
||||
public void setupAPIService(TestInfo test) throws HttpResponseException {
|
||||
APIServiceResourceTest apiServiceResourceTest = new APIServiceResourceTest();
|
||||
CreateAPIService createAPIService =
|
||||
CreateApiService createApiService =
|
||||
apiServiceResourceTest
|
||||
.createRequest(test)
|
||||
.withName("openmetadata")
|
||||
.withServiceType(CreateAPIService.APIServiceType.REST)
|
||||
.withServiceType(CreateApiService.ApiServiceType.Rest)
|
||||
.withConnection(TestUtils.API_SERVICE_CONNECTION);
|
||||
|
||||
APIService omAPIService =
|
||||
new APIServiceResourceTest().createEntity(createAPIService, ADMIN_AUTH_HEADERS);
|
||||
ApiService omAPIService =
|
||||
new APIServiceResourceTest().createEntity(createApiService, ADMIN_AUTH_HEADERS);
|
||||
OPENMETADATA_API_SERVICE_REFERENCE = omAPIService.getEntityReference();
|
||||
APIServiceResourceTest sampleAPIServiceResourceTest = new APIServiceResourceTest();
|
||||
createAPIService =
|
||||
createApiService =
|
||||
sampleAPIServiceResourceTest
|
||||
.createRequest(test)
|
||||
.withName("sampleAPI")
|
||||
.withServiceType(CreateAPIService.APIServiceType.REST)
|
||||
.withServiceType(CreateApiService.ApiServiceType.Rest)
|
||||
.withConnection(TestUtils.API_SERVICE_CONNECTION);
|
||||
APIService sampleAPIService =
|
||||
new APIServiceResourceTest().createEntity(createAPIService, ADMIN_AUTH_HEADERS);
|
||||
ApiService sampleAPIService =
|
||||
new APIServiceResourceTest().createEntity(createApiService, ADMIN_AUTH_HEADERS);
|
||||
SAMPLE_API_SERVICE_REFERENCE = sampleAPIService.getEntityReference();
|
||||
}
|
||||
|
||||
@ -93,26 +93,26 @@ public class APIServiceResourceTest extends ServiceResourceTest<APIService, Crea
|
||||
|
||||
@Test
|
||||
void put_updateService_as_admin_2xx(TestInfo test) throws IOException, URISyntaxException {
|
||||
APIServiceConnection connection1 =
|
||||
new APIServiceConnection()
|
||||
ApiConnection connection1 =
|
||||
new ApiConnection()
|
||||
.withConfig(
|
||||
new RESTConnection()
|
||||
new RestConnection()
|
||||
.withOpenAPISchemaURL(
|
||||
new URI("http://sandbox.open-metadata.org/swagger.json")));
|
||||
APIService service =
|
||||
ApiService service =
|
||||
createAndCheckEntity(
|
||||
createRequest(test).withDescription(null).withConnection(connection1),
|
||||
ADMIN_AUTH_HEADERS);
|
||||
|
||||
RESTConnection credentials2 =
|
||||
new RESTConnection()
|
||||
RestConnection credentials2 =
|
||||
new RestConnection()
|
||||
.withOpenAPISchemaURL(new URI("https://localhost:9400"))
|
||||
.withToken("test");
|
||||
APIServiceConnection connection2 = new APIServiceConnection().withConfig(credentials2);
|
||||
ApiConnection connection2 = new ApiConnection().withConfig(credentials2);
|
||||
|
||||
// Update APIService description and connection
|
||||
|
||||
CreateAPIService update =
|
||||
CreateApiService update =
|
||||
createRequest(test).withDescription("description1").withConnection(connection2);
|
||||
|
||||
ChangeDescription change = getChangeDescription(service, MINOR_UPDATE);
|
||||
@ -123,10 +123,10 @@ public class APIServiceResourceTest extends ServiceResourceTest<APIService, Crea
|
||||
|
||||
@Test
|
||||
void put_testConnectionResult_200(TestInfo test) throws IOException {
|
||||
APIService service = createAndCheckEntity(createRequest(test), ADMIN_AUTH_HEADERS);
|
||||
ApiService service = createAndCheckEntity(createRequest(test), ADMIN_AUTH_HEADERS);
|
||||
// By default, we have no result logged in
|
||||
assertNull(service.getTestConnectionResult());
|
||||
APIService updatedService =
|
||||
ApiService updatedService =
|
||||
putTestConnectionResult(service.getId(), TEST_CONNECTION_RESULT, ADMIN_AUTH_HEADERS);
|
||||
// Validate that the data got properly stored
|
||||
assertNotNull(updatedService.getTestConnectionResult());
|
||||
@ -135,50 +135,50 @@ public class APIServiceResourceTest extends ServiceResourceTest<APIService, Crea
|
||||
updatedService.getTestConnectionResult().getStatus());
|
||||
assertEquals(updatedService.getConnection(), service.getConnection());
|
||||
// Check that the stored data is also correct
|
||||
APIService stored = getEntity(service.getId(), ADMIN_AUTH_HEADERS);
|
||||
ApiService stored = getEntity(service.getId(), ADMIN_AUTH_HEADERS);
|
||||
assertNotNull(stored.getTestConnectionResult());
|
||||
assertEquals(
|
||||
TestConnectionResultStatus.SUCCESSFUL, stored.getTestConnectionResult().getStatus());
|
||||
assertEquals(stored.getConnection(), service.getConnection());
|
||||
}
|
||||
|
||||
public APIService putTestConnectionResult(
|
||||
public ApiService putTestConnectionResult(
|
||||
UUID serviceId, TestConnectionResult testConnectionResult, Map<String, String> authHeaders)
|
||||
throws HttpResponseException {
|
||||
WebTarget target = getResource(serviceId).path("/testConnectionResult");
|
||||
return TestUtils.put(target, testConnectionResult, APIService.class, OK, authHeaders);
|
||||
return TestUtils.put(target, testConnectionResult, ApiService.class, OK, authHeaders);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CreateAPIService createRequest(String name) {
|
||||
return new CreateAPIService()
|
||||
public CreateApiService createRequest(String name) {
|
||||
return new CreateApiService()
|
||||
.withName(name)
|
||||
.withServiceType(CreateAPIService.APIServiceType.REST)
|
||||
.withServiceType(CreateApiService.ApiServiceType.Rest)
|
||||
.withConnection(
|
||||
new APIServiceConnection()
|
||||
new ApiConnection()
|
||||
.withConfig(
|
||||
new RESTConnection()
|
||||
new RestConnection()
|
||||
.withOpenAPISchemaURL(
|
||||
CommonUtil.getUri("http://localhost:8585/swagger.json"))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateCreatedEntity(
|
||||
APIService service, CreateAPIService createRequest, Map<String, String> authHeaders) {
|
||||
ApiService service, CreateApiService createRequest, Map<String, String> authHeaders) {
|
||||
assertEquals(createRequest.getName(), service.getName());
|
||||
APIServiceConnection expectedConnection = createRequest.getConnection();
|
||||
APIServiceConnection actualConnection = service.getConnection();
|
||||
ApiConnection expectedConnection = createRequest.getConnection();
|
||||
ApiConnection actualConnection = service.getConnection();
|
||||
validateConnection(expectedConnection, actualConnection, service.getServiceType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compareEntities(
|
||||
APIService expected, APIService updated, Map<String, String> authHeaders) {
|
||||
ApiService expected, ApiService updated, Map<String, String> authHeaders) {
|
||||
// PATCH operation is not supported by this entity
|
||||
}
|
||||
|
||||
@Override
|
||||
public APIService validateGetWithDifferentFields(APIService service, boolean byName)
|
||||
public ApiService validateGetWithDifferentFields(ApiService service, boolean byName)
|
||||
throws HttpResponseException {
|
||||
String fields = "";
|
||||
service =
|
||||
@ -209,13 +209,13 @@ public class APIServiceResourceTest extends ServiceResourceTest<APIService, Crea
|
||||
}
|
||||
|
||||
private void validateConnection(
|
||||
APIServiceConnection expectedConnection,
|
||||
APIServiceConnection actualConnection,
|
||||
CreateAPIService.APIServiceType serviceType) {
|
||||
ApiConnection expectedConnection,
|
||||
ApiConnection actualConnection,
|
||||
CreateApiService.ApiServiceType serviceType) {
|
||||
if (expectedConnection != null && actualConnection != null) {
|
||||
RESTConnection restConnection = (RESTConnection) expectedConnection.getConfig();
|
||||
RESTConnection actualESConnection =
|
||||
JsonUtils.convertValue(actualConnection.getConfig(), RESTConnection.class);
|
||||
RestConnection restConnection = (RestConnection) expectedConnection.getConfig();
|
||||
RestConnection actualESConnection =
|
||||
JsonUtils.convertValue(actualConnection.getConfig(), RestConnection.class);
|
||||
assertEquals(restConnection.getOpenAPISchemaURL(), actualESConnection.getOpenAPISchemaURL());
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,7 +67,7 @@ import org.openmetadata.schema.entity.teams.User;
|
||||
import org.openmetadata.schema.entity.type.CustomProperty;
|
||||
import org.openmetadata.schema.entity.type.Style;
|
||||
import org.openmetadata.schema.security.credentials.AWSCredentials;
|
||||
import org.openmetadata.schema.services.connections.api.RESTConnection;
|
||||
import org.openmetadata.schema.services.connections.api.RestConnection;
|
||||
import org.openmetadata.schema.services.connections.database.BigQueryConnection;
|
||||
import org.openmetadata.schema.services.connections.database.MysqlConnection;
|
||||
import org.openmetadata.schema.services.connections.database.RedshiftConnection;
|
||||
@ -83,7 +83,7 @@ import org.openmetadata.schema.services.connections.pipeline.GluePipelineConnect
|
||||
import org.openmetadata.schema.services.connections.search.ElasticSearchConnection;
|
||||
import org.openmetadata.schema.services.connections.search.OpenSearchConnection;
|
||||
import org.openmetadata.schema.services.connections.storage.S3Connection;
|
||||
import org.openmetadata.schema.type.APIServiceConnection;
|
||||
import org.openmetadata.schema.type.ApiConnection;
|
||||
import org.openmetadata.schema.type.EntityReference;
|
||||
import org.openmetadata.schema.type.MessagingConnection;
|
||||
import org.openmetadata.schema.type.MlModelConnection;
|
||||
@ -183,10 +183,10 @@ public final class TestUtils {
|
||||
new SearchConnection()
|
||||
.withConfig(new OpenSearchConnection().withHostPort("http://localhost:9200"));
|
||||
|
||||
public static final APIServiceConnection API_SERVICE_CONNECTION =
|
||||
new APIServiceConnection()
|
||||
public static final ApiConnection API_SERVICE_CONNECTION =
|
||||
new ApiConnection()
|
||||
.withConfig(
|
||||
new RESTConnection()
|
||||
new RestConnection()
|
||||
.withOpenAPISchemaURL(getUri("http://localhost:8585/swagger.json")));
|
||||
|
||||
public static final MetadataConnection AMUNDSEN_CONNECTION =
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
{
|
||||
"$id": "https://open-metadata.org/schema/api/services/createAPIService.json",
|
||||
"$id": "https://open-metadata.org/schema/api/services/createApiService.json",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "CreateApiServiceRequest",
|
||||
"description": "Create API Service entity request",
|
||||
"type": "object",
|
||||
"javaType": "org.openmetadata.schema.api.services.CreateAPIService",
|
||||
"javaType": "org.openmetadata.schema.api.services.CreateApiService",
|
||||
"javaInterfaces": ["org.openmetadata.schema.CreateEntity"],
|
||||
|
||||
"properties": {
|
||||
@ -21,10 +21,10 @@
|
||||
"$ref": "../../type/basic.json#/definitions/markdown"
|
||||
},
|
||||
"serviceType": {
|
||||
"$ref": "../../entity/services/apiService.json#/definitions/APIServiceType"
|
||||
"$ref": "../../entity/services/apiService.json#/definitions/apiServiceType"
|
||||
},
|
||||
"connection": {
|
||||
"$ref": "../../entity/services/apiService.json#/definitions/apiServiceConnection"
|
||||
"$ref": "../../entity/services/apiService.json#/definitions/apiConnection"
|
||||
},
|
||||
"tags": {
|
||||
"description": "Tags for this API Service.",
|
||||
|
||||
@ -9,6 +9,9 @@
|
||||
"connection": {
|
||||
"description": "Connection object.",
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "../services/apiService.json#/definitions/apiConnection"
|
||||
},
|
||||
{
|
||||
"$ref": "../services/databaseService.json#/definitions/databaseConnection"
|
||||
},
|
||||
|
||||
@ -74,7 +74,7 @@
|
||||
},
|
||||
"serviceType": {
|
||||
"description": "Service type where this API Collection is hosted in.",
|
||||
"$ref": "../services/apiService.json#/definitions/APIServiceType"
|
||||
"$ref": "../services/apiService.json#/definitions/apiServiceType"
|
||||
},
|
||||
"changeDescription": {
|
||||
"description": "Change that lead to this version of the entity.",
|
||||
|
||||
@ -136,7 +136,7 @@
|
||||
},
|
||||
"serviceType": {
|
||||
"description": "Service type where this API Collection is hosted in.",
|
||||
"$ref": "../services/apiService.json#/definitions/APIServiceType"
|
||||
"$ref": "../services/apiService.json#/definitions/apiServiceType"
|
||||
},
|
||||
"changeDescription": {
|
||||
"description": "Change that lead to this version of the entity.",
|
||||
|
||||
@ -1,37 +1,37 @@
|
||||
{
|
||||
"$id": "https://open-metadata.org/schema/entity/services/apiService.json",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "API Service",
|
||||
"title": "Api Service",
|
||||
"description": "This schema defines the API Service entity, to capture metadata from any REST API Services.",
|
||||
"type": "object",
|
||||
"javaType": "org.openmetadata.schema.entity.services.APIService",
|
||||
"javaType": "org.openmetadata.schema.entity.services.ApiService",
|
||||
"javaInterfaces": [
|
||||
"org.openmetadata.schema.EntityInterface",
|
||||
"org.openmetadata.schema.ServiceEntityInterface"
|
||||
],
|
||||
"definitions": {
|
||||
"APIServiceType": {
|
||||
"apiServiceType": {
|
||||
"description": "Type of api service such as REST, Webhook,...",
|
||||
"javaInterfaces": [
|
||||
"org.openmetadata.schema.EnumInterface"
|
||||
],
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"REST",
|
||||
"Rest",
|
||||
"WEBHOOK"
|
||||
],
|
||||
"javaEnums": [
|
||||
{
|
||||
"name": "REST"
|
||||
"name": "Rest"
|
||||
},
|
||||
{
|
||||
"name": "WEBHOOK"
|
||||
}
|
||||
]
|
||||
},
|
||||
"apiServiceConnection": {
|
||||
"apiConnection": {
|
||||
"type": "object",
|
||||
"javaType": "org.openmetadata.schema.type.APIServiceConnection",
|
||||
"javaType": "org.openmetadata.schema.type.ApiConnection",
|
||||
"description": "API Service Connection.",
|
||||
"javaInterfaces": [
|
||||
"org.openmetadata.schema.ServiceConnectionEntityInterface"
|
||||
@ -41,7 +41,7 @@
|
||||
"mask": true,
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "./connections/apiService/restConnection.json"
|
||||
"$ref": "./connections/api/restConnection.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -68,14 +68,14 @@
|
||||
},
|
||||
"serviceType": {
|
||||
"description": "Type of API service such as REST, WEBHOOK..",
|
||||
"$ref": "#/definitions/APIServiceType"
|
||||
"$ref": "#/definitions/apiServiceType"
|
||||
},
|
||||
"description": {
|
||||
"description": "Description of a API service instance.",
|
||||
"$ref": "../../type/basic.json#/definitions/markdown"
|
||||
},
|
||||
"connection": {
|
||||
"$ref": "#/definitions/apiServiceConnection"
|
||||
"$ref": "#/definitions/apiConnection"
|
||||
},
|
||||
"pipelines": {
|
||||
"description": "References to pipelines deployed for this API service to extract metadata, usage, lineage etc..",
|
||||
|
||||
@ -1,24 +1,24 @@
|
||||
{
|
||||
"$id": "https://open-metadata.org/schema/entity/services/connections/apiService/restConnection.json",
|
||||
"$id": "https://open-metadata.org/schema/entity/services/connections/api/restConnection.json",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "RESTConnection",
|
||||
"title": "RestConnection",
|
||||
"description": "REST Connection Config",
|
||||
"type": "object",
|
||||
"javaType": "org.openmetadata.schema.services.connections.api.RESTConnection",
|
||||
"javaType": "org.openmetadata.schema.services.connections.api.RestConnection",
|
||||
"definitions": {
|
||||
"RESTAPIType": {
|
||||
"restType": {
|
||||
"description": "REST API type",
|
||||
"type": "string",
|
||||
"enum": ["REST"],
|
||||
"default": "REST"
|
||||
"enum": ["Rest"],
|
||||
"default": "Rest"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"type": {
|
||||
"title": "REST API Type",
|
||||
"description": "REST API Type",
|
||||
"$ref": "#/definitions/RESTAPIType",
|
||||
"default": "REST"
|
||||
"$ref": "#/definitions/restType",
|
||||
"default": "Rest"
|
||||
},
|
||||
"openAPISchemaURL": {
|
||||
"expose": true,
|
||||
@ -9,7 +9,7 @@
|
||||
"description": "Supported services",
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "../apiService.json#/definitions/apiServiceConnection"
|
||||
"$ref": "../apiService.json#/definitions/apiConnection"
|
||||
},
|
||||
{
|
||||
"$ref": "../dashboardService.json#/definitions/dashboardConnection"
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
"Pipeline",
|
||||
"Storage",
|
||||
"Search",
|
||||
"API"
|
||||
"Api"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ test.describe('API service', () => {
|
||||
await settingClick(page, GlobalSettingOptions.APIS);
|
||||
|
||||
await page.getByTestId('add-service-button').click();
|
||||
await page.getByTestId('REST').click();
|
||||
await page.getByTestId('Rest').click();
|
||||
await page.getByTestId('next-button').click();
|
||||
|
||||
// step 1
|
||||
|
||||
@ -16,6 +16,7 @@ import { PLAYWRIGHT_INGESTION_TAG_OBJ } from '../../constant/config';
|
||||
import { MYSQL, POSTGRES, REDSHIFT } from '../../constant/service';
|
||||
import { GlobalSettingOptions } from '../../constant/settings';
|
||||
import AirflowIngestionClass from '../../support/entity/ingestion/AirflowIngestionClass';
|
||||
import ApiIngestionClass from '../../support/entity/ingestion/ApiIngestionClass';
|
||||
import BigQueryIngestionClass from '../../support/entity/ingestion/BigQueryIngestionClass';
|
||||
import KafkaIngestionClass from '../../support/entity/ingestion/KafkaIngestionClass';
|
||||
import MetabaseIngestionClass from '../../support/entity/ingestion/MetabaseIngestionClass';
|
||||
@ -30,6 +31,7 @@ import { INVALID_NAMES, redirectToHomePage } from '../../utils/common';
|
||||
import { settingClick, SettingOptionsType } from '../../utils/sidebar';
|
||||
|
||||
const services = [
|
||||
ApiIngestionClass,
|
||||
S3IngestionClass,
|
||||
MetabaseIngestionClass,
|
||||
MysqlIngestionClass,
|
||||
|
||||
@ -24,10 +24,10 @@ export class ApiCollectionClass extends EntityClass {
|
||||
private apiCollectionName = `pw-api-collection-${uuid()}`;
|
||||
service = {
|
||||
name: this.serviceName,
|
||||
serviceType: 'REST',
|
||||
serviceType: 'Rest',
|
||||
connection: {
|
||||
config: {
|
||||
type: 'REST',
|
||||
type: 'Rest',
|
||||
openAPISchemaURL: 'https://sandbox-beta.open-metadata.org/swagger.json',
|
||||
},
|
||||
},
|
||||
|
||||
@ -23,10 +23,10 @@ export class ApiEndpointClass extends EntityClass {
|
||||
private apiCollectionName = `pw-api-collection-${uuid()}`;
|
||||
service = {
|
||||
name: this.serviceName,
|
||||
serviceType: 'REST',
|
||||
serviceType: 'Rest',
|
||||
connection: {
|
||||
config: {
|
||||
type: 'REST',
|
||||
type: 'Rest',
|
||||
openAPISchemaURL: 'https://sandbox-beta.open-metadata.org/swagger.json',
|
||||
},
|
||||
},
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2024 Collate.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import { Page } from '@playwright/test';
|
||||
import { uuid } from '../../../utils/common';
|
||||
import {
|
||||
checkServiceFieldSectionHighlighting,
|
||||
Services,
|
||||
} from '../../../utils/serviceIngestion';
|
||||
import ServiceBaseClass from './ServiceBaseClass';
|
||||
|
||||
class ApiIngestionClass extends ServiceBaseClass {
|
||||
constructor() {
|
||||
super(Services.API, `pw-api-with-%-${uuid()}`, 'Rest', 'Containers');
|
||||
}
|
||||
|
||||
async createService(page: Page) {
|
||||
await super.createService(page);
|
||||
}
|
||||
|
||||
async updateService(page: Page) {
|
||||
await super.updateService(page);
|
||||
}
|
||||
|
||||
async fillConnectionDetails(page: Page) {
|
||||
const openAPISchemaURL = 'https://docs.open-metadata.org/swagger.json';
|
||||
|
||||
await page.locator('#root\\/openAPISchemaURL').fill(openAPISchemaURL);
|
||||
await checkServiceFieldSectionHighlighting(page, 'openAPISchemaURL');
|
||||
}
|
||||
|
||||
async deleteService(page: Page): Promise<void> {
|
||||
await super.deleteService(page);
|
||||
}
|
||||
}
|
||||
|
||||
export default ApiIngestionClass;
|
||||
@ -21,10 +21,10 @@ import { EntityClass } from '../EntityClass';
|
||||
export class ApiServiceClass extends EntityClass {
|
||||
entity = {
|
||||
name: `pw-api-service-${uuid()}`,
|
||||
serviceType: 'REST',
|
||||
serviceType: 'Rest',
|
||||
connection: {
|
||||
config: {
|
||||
type: 'REST',
|
||||
type: 'Rest',
|
||||
openAPISchemaURL: 'https://sandbox-beta.open-metadata.org/swagger.json',
|
||||
},
|
||||
},
|
||||
|
||||
@ -24,6 +24,7 @@ export enum Services {
|
||||
MLModels = GlobalSettingOptions.MLMODELS,
|
||||
Storage = GlobalSettingOptions.STORAGES,
|
||||
Search = GlobalSettingOptions.SEARCH,
|
||||
API = GlobalSettingOptions.APIS,
|
||||
}
|
||||
|
||||
export const getEntityTypeFromService = (service: Services) => {
|
||||
@ -42,6 +43,8 @@ export const getEntityTypeFromService = (service: Services) => {
|
||||
return EntityTypeEndpoint.MlModelService;
|
||||
case Services.Pipeline:
|
||||
return EntityTypeEndpoint.PipelineService;
|
||||
case Services.API:
|
||||
return EntityTypeEndpoint.ApiService;
|
||||
default:
|
||||
return EntityTypeEndpoint.DatabaseService;
|
||||
}
|
||||
@ -63,6 +66,8 @@ export const getServiceCategoryFromService = (service: Services) => {
|
||||
return 'mlmodelService';
|
||||
case Services.Pipeline:
|
||||
return 'pipelineService';
|
||||
case Services.API:
|
||||
return 'apiService';
|
||||
default:
|
||||
return 'databaseService';
|
||||
}
|
||||
|
||||
@ -0,0 +1,44 @@
|
||||
# Metadata
|
||||
|
||||
API Service Metadata Pipeline Configuration.
|
||||
|
||||
$$section
|
||||
### API Collection Filter Pattern $(id="apiCollectionFilterPattern")
|
||||
|
||||
API Collection filter patterns to control whether to include API Collections as part of metadata ingestion.
|
||||
|
||||
**Include**: Explicitly include API Collections by adding a list of regular expressions to the `Include` field. OpenMetadata will include all API Collections with names matching one or more of the supplied regular expressions. All other API Collections will be excluded.
|
||||
|
||||
For example, to include only those API Collections whose name starts with the word `demo`, add the regex pattern in the include field as `^demo.*`.
|
||||
|
||||
**Exclude**: Explicitly exclude API Collections by adding a list of regular expressions to the `Exclude` field. OpenMetadata will exclude all API Collections with names matching one or more of the supplied regular expressions. All other API Collections will be included.
|
||||
|
||||
For example, to exclude all API Collections with the name containing the word `demo`, add the regex pattern in the exclude field as `.*demo.*`.
|
||||
|
||||
Checkout [this](https://docs.open-metadata.org/connectors/ingestion/workflows/metadata/filter-patterns/database#database-filter-pattern) document for further examples on filter patterns.
|
||||
$$
|
||||
|
||||
$$section
|
||||
### Enable Debug Logs $(id="enableDebugLog")
|
||||
|
||||
Set the `Enable Debug Log` toggle to set the logging level of the process to debug. You can check these logs in the Ingestion tab of the service and dig deeper into any errors you might find.
|
||||
$$
|
||||
|
||||
$$section
|
||||
### Mark Deleted API Collection $(id="markDeletedApiCollections")
|
||||
|
||||
Optional configuration to soft delete `API Collections` in OpenMetadata if the source `API Collections` are deleted. After deleting, all the associated entities like lineage, etc., with that `API Collection` will be deleted.
|
||||
$$
|
||||
|
||||
$$section
|
||||
### Override Metadata $(id="overrideMetadata")
|
||||
|
||||
Set the `Override Metadata` toggle to control whether to override the existing metadata in the OpenMetadata server with the metadata fetched from the source.
|
||||
|
||||
If the toggle is `enabled`, the metadata fetched from the source will override and replace the existing metadata in the OpenMetadata.
|
||||
|
||||
If the toggle is `disabled`, the metadata fetched from the source will not override the existing metadata in the OpenMetadata server. In this case the metadata will only get updated for fields that has no value added in OpenMetadata.
|
||||
|
||||
This is applicable for fields like description, tags, owner and displayName
|
||||
|
||||
$$
|
||||
@ -243,13 +243,10 @@ const AddService = ({
|
||||
|
||||
{activeServiceStep > 3 && (
|
||||
<SuccessScreen
|
||||
showIngestionButton
|
||||
handleIngestionClick={() => handleAddIngestion(true)}
|
||||
handleViewServiceClick={handleViewServiceClick}
|
||||
name={serviceConfig.serviceName}
|
||||
// API Service does not support ingestion workflows
|
||||
showIngestionButton={
|
||||
serviceCategory !== ServiceCategory.API_SERVICES
|
||||
}
|
||||
state={FormSubmitType.ADD}
|
||||
suffix={getServiceCreatedLabel(serviceCategory)}
|
||||
/>
|
||||
|
||||
@ -83,14 +83,16 @@ const ServiceDocPanel: FC<ServiceDocPanelProp> = ({
|
||||
const fetchRequirement = async () => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const supportedServiceType =
|
||||
serviceType === 'Api' ? 'ApiEntity' : serviceType;
|
||||
let response = '';
|
||||
const isEnglishLanguage = i18n.language === SupportedLocales.English;
|
||||
let filePath = `${i18n.language}/${serviceType}/${serviceName}.md`;
|
||||
let fallbackFilePath = `${SupportedLocales.English}/${serviceType}/${serviceName}.md`;
|
||||
let filePath = `${i18n.language}/${supportedServiceType}/${serviceName}.md`;
|
||||
let fallbackFilePath = `${SupportedLocales.English}/${supportedServiceType}/${serviceName}.md`;
|
||||
|
||||
if (isWorkflow && workflowType) {
|
||||
filePath = `${i18n.language}/${serviceType}/workflows/${workflowType}.md`;
|
||||
fallbackFilePath = `${SupportedLocales.English}/${serviceType}/workflows/${workflowType}.md`;
|
||||
filePath = `${i18n.language}/${supportedServiceType}/workflows/${workflowType}.md`;
|
||||
fallbackFilePath = `${SupportedLocales.English}/${supportedServiceType}/workflows/${workflowType}.md`;
|
||||
}
|
||||
|
||||
const [translation, fallbackTranslation] = await Promise.allSettled([
|
||||
|
||||
@ -417,7 +417,6 @@ export const BETA_SERVICES = [
|
||||
PipelineServiceType.OpenLineage,
|
||||
PipelineServiceType.Flink,
|
||||
DatabaseServiceType.Teradata,
|
||||
APIServiceType.REST,
|
||||
StorageServiceType.Gcs,
|
||||
DatabaseServiceType.SapERP,
|
||||
PipelineServiceType.Flink,
|
||||
|
||||
@ -1021,22 +1021,21 @@ const ServiceDetailsPage: FunctionComponent = () => {
|
||||
});
|
||||
}
|
||||
|
||||
if (serviceCategory !== ServiceCategory.API_SERVICES) {
|
||||
tabs.push({
|
||||
tabs.push(
|
||||
{
|
||||
name: t('label.ingestion-plural'),
|
||||
key: EntityTabs.INGESTIONS,
|
||||
isHidden: !showIngestionTab,
|
||||
count: ingestionPaging.total,
|
||||
children: ingestionTab,
|
||||
});
|
||||
}
|
||||
|
||||
tabs.push({
|
||||
name: t('label.connection'),
|
||||
isHidden: !servicePermission.EditAll,
|
||||
key: EntityTabs.CONNECTION,
|
||||
children: testConnectionTab,
|
||||
});
|
||||
},
|
||||
{
|
||||
name: t('label.connection'),
|
||||
isHidden: !servicePermission.EditAll,
|
||||
key: EntityTabs.CONNECTION,
|
||||
children: testConnectionTab,
|
||||
}
|
||||
);
|
||||
|
||||
return tabs
|
||||
.filter((tab) => !tab.isHidden)
|
||||
|
||||
@ -105,8 +105,7 @@ const ServicesPage = () => {
|
||||
label: 'Services',
|
||||
},
|
||||
]),
|
||||
// pipelines are not supported for apiServices so don't show pipelines tab for apiServices
|
||||
...(isAdminUser && serviceName !== 'apiServices'
|
||||
...(isAdminUser
|
||||
? [
|
||||
{
|
||||
key: 'pipelines',
|
||||
|
||||
@ -13,14 +13,14 @@
|
||||
import { cloneDeep } from 'lodash';
|
||||
import { COMMON_UI_SCHEMA } from '../constants/Services.constant';
|
||||
import { APIServiceType } from '../generated/entity/services/apiService';
|
||||
import RESTConnection from '../jsons/connectionSchemas/connections/apiService/restConnection.json';
|
||||
import restConnection from '../jsons/connectionSchemas/connections/api/restConnection.json';
|
||||
|
||||
export const getAPIConfig = (type: APIServiceType) => {
|
||||
let schema = {};
|
||||
const uiSchema = { ...COMMON_UI_SCHEMA };
|
||||
switch (type) {
|
||||
case APIServiceType.REST:
|
||||
schema = RESTConnection;
|
||||
schema = restConnection;
|
||||
|
||||
break;
|
||||
|
||||
|
||||
@ -117,6 +117,16 @@ class GlobalSettingsClassBase {
|
||||
icon: ServiceIcon,
|
||||
description: t('message.service-description'),
|
||||
items: [
|
||||
{
|
||||
label: t('label.api-uppercase-plural'),
|
||||
description: t('message.page-sub-header-for-apis'),
|
||||
isProtected: userPermissions.hasViewPermissions(
|
||||
ResourceEntity.API_SERVICE,
|
||||
permissions
|
||||
),
|
||||
key: `${GlobalSettingsMenuCategory.SERVICES}.${GlobalSettingOptions.APIS}`,
|
||||
icon: IconAPI,
|
||||
},
|
||||
{
|
||||
label: t('label.database-plural'),
|
||||
description: t('message.page-sub-header-for-databases'),
|
||||
@ -197,17 +207,6 @@ class GlobalSettingsClassBase {
|
||||
key: `${GlobalSettingsMenuCategory.SERVICES}.${GlobalSettingOptions.METADATA}`,
|
||||
icon: OpenMetadataIcon,
|
||||
},
|
||||
{
|
||||
label: t('label.api-uppercase-plural'),
|
||||
description: t('message.page-sub-header-for-apis'),
|
||||
isProtected: userPermissions.hasViewPermissions(
|
||||
ResourceEntity.API_SERVICE,
|
||||
permissions
|
||||
),
|
||||
key: `${GlobalSettingsMenuCategory.SERVICES}.${GlobalSettingOptions.APIS}`,
|
||||
icon: IconAPI,
|
||||
isBeta: true,
|
||||
},
|
||||
{
|
||||
label: t('label.data-observability'),
|
||||
description: t('message.page-sub-header-for-data-observability'),
|
||||
|
||||
@ -29,7 +29,6 @@ import { ServiceCategory } from '../enums/service.enum';
|
||||
import { StorageServiceType } from '../generated/entity/data/container';
|
||||
import { Database } from '../generated/entity/data/database';
|
||||
import { MlModelServiceType } from '../generated/entity/data/mlmodel';
|
||||
import { APIServiceType } from '../generated/entity/services/apiService';
|
||||
import {
|
||||
DashboardService,
|
||||
DashboardServiceType,
|
||||
@ -100,8 +99,7 @@ export const shouldTestConnection = (serviceType: string) => {
|
||||
serviceType !== DashboardServiceType.CustomDashboard &&
|
||||
serviceType !== MlModelServiceType.CustomMlModel &&
|
||||
serviceType !== PipelineServiceType.CustomPipeline &&
|
||||
serviceType !== StorageServiceType.CustomStorage &&
|
||||
serviceType !== APIServiceType.REST
|
||||
serviceType !== StorageServiceType.CustomStorage
|
||||
);
|
||||
};
|
||||
|
||||
@ -348,7 +346,7 @@ export const getServiceRouteFromServiceType = (type: ServiceTypes) => {
|
||||
return GlobalSettingOptions.SEARCH;
|
||||
}
|
||||
|
||||
if (type === 'apiServices') {
|
||||
if (type === ServiceCategory.API_SERVICES) {
|
||||
return GlobalSettingOptions.APIS;
|
||||
}
|
||||
|
||||
@ -387,7 +385,6 @@ export const getResourceEntityFromServiceCategory = (
|
||||
case ServiceCategory.STORAGE_SERVICES:
|
||||
return ResourceEntity.STORAGE_SERVICE;
|
||||
|
||||
case 'apiServices':
|
||||
case ServiceCategory.API_SERVICES:
|
||||
return ResourceEntity.API_SERVICE;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user