mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-18 05:57:17 +00:00
Use source when creating and updating indexes (#5597)
This commit is contained in:
parent
e640db3192
commit
816f8d49eb
@ -118,6 +118,48 @@ public class AirflowRESTClient extends PipelineServiceClient {
|
|||||||
pipelineName, "Failed to trigger IngestionPipeline", Response.Status.fromStatusCode(response.statusCode()));
|
pipelineName, "Failed to trigger IngestionPipeline", Response.Status.fromStatusCode(response.statusCode()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IngestionPipeline toggleIngestion(IngestionPipeline ingestionPipeline) {
|
||||||
|
HttpResponse<String> response;
|
||||||
|
try {
|
||||||
|
String toggleEndPoint;
|
||||||
|
String toggleUrl;
|
||||||
|
JSONObject requestPayload = new JSONObject();
|
||||||
|
requestPayload.put("dag_id", ingestionPipeline.getName());
|
||||||
|
// If the pipeline is currently enabled, disable it
|
||||||
|
if (ingestionPipeline.getEnabled().equals(Boolean.TRUE)) {
|
||||||
|
toggleEndPoint = "%s/rest_api/api?api=disable_dag";
|
||||||
|
toggleUrl = String.format(toggleEndPoint, serviceURL);
|
||||||
|
response = post(toggleUrl, requestPayload.toString());
|
||||||
|
if (response.statusCode() == 200) {
|
||||||
|
ingestionPipeline.setEnabled(false);
|
||||||
|
return ingestionPipeline;
|
||||||
|
} else if (response.statusCode() == 404) {
|
||||||
|
ingestionPipeline.setDeployed(false);
|
||||||
|
return ingestionPipeline;
|
||||||
|
}
|
||||||
|
// otherwise, enable it back
|
||||||
|
} else {
|
||||||
|
toggleEndPoint = "%s/rest_api/api?api=enable_dag";
|
||||||
|
toggleUrl = String.format(toggleEndPoint, serviceURL);
|
||||||
|
response = post(toggleUrl, requestPayload.toString());
|
||||||
|
if (response.statusCode() == 200) {
|
||||||
|
ingestionPipeline.setEnabled(true);
|
||||||
|
return ingestionPipeline;
|
||||||
|
} else if (response.statusCode() == 404) {
|
||||||
|
ingestionPipeline.setDeployed(false);
|
||||||
|
return ingestionPipeline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw PipelineServiceClientException.byMessage(ingestionPipeline.getName(), e.getMessage());
|
||||||
|
}
|
||||||
|
throw PipelineServiceClientException.byMessage(
|
||||||
|
ingestionPipeline.getName(),
|
||||||
|
"Failed to toggle ingestion pipeline state",
|
||||||
|
Response.Status.fromStatusCode(response.statusCode()));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IngestionPipeline getPipelineStatus(IngestionPipeline ingestionPipeline) {
|
public IngestionPipeline getPipelineStatus(IngestionPipeline ingestionPipeline) {
|
||||||
HttpResponse<String> response;
|
HttpResponse<String> response;
|
||||||
|
@ -33,8 +33,8 @@ import org.openmetadata.catalog.util.JsonUtils;
|
|||||||
import org.openmetadata.catalog.util.PipelineServiceClient;
|
import org.openmetadata.catalog.util.PipelineServiceClient;
|
||||||
|
|
||||||
public class IngestionPipelineRepository extends EntityRepository<IngestionPipeline> {
|
public class IngestionPipelineRepository extends EntityRepository<IngestionPipeline> {
|
||||||
private static final String INGESTION_PIPELINE_UPDATE_FIELDS = "owner,sourceConfig,airflowConfig,loggerLevel";
|
private static final String INGESTION_PIPELINE_UPDATE_FIELDS = "owner,sourceConfig,airflowConfig,loggerLevel,enabled";
|
||||||
private static final String INGESTION_PIPELINE_PATCH_FIELDS = "owner,sourceConfig,airflowConfig,loggerLevel";
|
private static final String INGESTION_PIPELINE_PATCH_FIELDS = "owner,sourceConfig,airflowConfig,loggerLevel,enabled";
|
||||||
private static PipelineServiceClient pipelineServiceClient;
|
private static PipelineServiceClient pipelineServiceClient;
|
||||||
|
|
||||||
public IngestionPipelineRepository(CollectionDAO dao) {
|
public IngestionPipelineRepository(CollectionDAO dao) {
|
||||||
@ -129,6 +129,7 @@ public class IngestionPipelineRepository extends EntityRepository<IngestionPipel
|
|||||||
updateOpenMetadataServerConnection(
|
updateOpenMetadataServerConnection(
|
||||||
original.getOpenMetadataServerConnection(), updated.getOpenMetadataServerConnection());
|
original.getOpenMetadataServerConnection(), updated.getOpenMetadataServerConnection());
|
||||||
updateLogLevel(original.getLoggerLevel(), updated.getLoggerLevel());
|
updateLogLevel(original.getLoggerLevel(), updated.getLoggerLevel());
|
||||||
|
updateEnabled(original.getEnabled(), updated.getEnabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateSourceConfig(SourceConfig origSource, SourceConfig updatedSource)
|
private void updateSourceConfig(SourceConfig origSource, SourceConfig updatedSource)
|
||||||
@ -161,5 +162,11 @@ public class IngestionPipelineRepository extends EntityRepository<IngestionPipel
|
|||||||
recordChange("loggerLevel", origLevel, updatedLevel);
|
recordChange("loggerLevel", origLevel, updatedLevel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateEnabled(Boolean origEnabled, Boolean updatedEnabled) throws JsonProcessingException {
|
||||||
|
if (updatedEnabled != null && !origEnabled.equals(updatedEnabled)) {
|
||||||
|
recordChange("enabled", origEnabled, updatedEnabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -416,6 +416,31 @@ public class IngestionPipelineResource extends EntityResource<IngestionPipeline,
|
|||||||
return addHref(uriInfo, dao.get(uriInfo, id, fields));
|
return addHref(uriInfo, dao.get(uriInfo, id, fields));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/toggleIngestion/{id}")
|
||||||
|
@Operation(
|
||||||
|
operationId = "toggleIngestionPipelineEnabled",
|
||||||
|
summary = "Set an Ingestion pipeline either as Enabled or Disabled",
|
||||||
|
tags = "IngestionPipelines",
|
||||||
|
description = "Toggle an ingestion pipeline state by id.",
|
||||||
|
responses = {
|
||||||
|
@ApiResponse(
|
||||||
|
responseCode = "200",
|
||||||
|
description = "The ingestion",
|
||||||
|
content =
|
||||||
|
@Content(mediaType = "application/json", schema = @Schema(implementation = IngestionPipeline.class))),
|
||||||
|
@ApiResponse(responseCode = "404", description = "Ingestion for instance {id} is not found")
|
||||||
|
})
|
||||||
|
public Response toggleIngestion(
|
||||||
|
@Context UriInfo uriInfo, @PathParam("id") String id, @Context SecurityContext securityContext)
|
||||||
|
throws IOException {
|
||||||
|
Fields fields = getFields(FIELD_OWNER);
|
||||||
|
IngestionPipeline pipeline = dao.get(uriInfo, id, fields);
|
||||||
|
// This call updates the state in Airflow as well as the `enabled` field on the IngestionPipeline
|
||||||
|
pipelineServiceClient.toggleIngestion(pipeline);
|
||||||
|
return createOrUpdate(uriInfo, securityContext, pipeline, ADMIN | BOT | OWNER);
|
||||||
|
}
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Path("/testConnection")
|
@Path("/testConnection")
|
||||||
@Operation(
|
@Operation(
|
||||||
|
@ -88,6 +88,9 @@ public abstract class PipelineServiceClient {
|
|||||||
/* Get the status of a deployed pipeline */
|
/* Get the status of a deployed pipeline */
|
||||||
public abstract IngestionPipeline getPipelineStatus(IngestionPipeline ingestionPipeline);
|
public abstract IngestionPipeline getPipelineStatus(IngestionPipeline ingestionPipeline);
|
||||||
|
|
||||||
|
/* Toggle the state of an Ingestion Pipeline as enabled/disabled */
|
||||||
|
public abstract IngestionPipeline toggleIngestion(IngestionPipeline ingestionPipeline);
|
||||||
|
|
||||||
/* Get the all last run logs of a deployed pipeline */
|
/* Get the all last run logs of a deployed pipeline */
|
||||||
public abstract Map<String, String> getLastIngestionLogs(String pipelineName);
|
public abstract Map<String, String> getLastIngestionLogs(String pipelineName);
|
||||||
}
|
}
|
||||||
|
@ -170,6 +170,11 @@
|
|||||||
"description": "Indicates if the workflow has been successfully deployed to Airflow.",
|
"description": "Indicates if the workflow has been successfully deployed to Airflow.",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"enabled": {
|
||||||
|
"description": "True if the pipeline is ready to be run in the next schedule. False if it is paused.",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
"href": {
|
"href": {
|
||||||
"description": "Link to this ingestion pipeline resource.",
|
"description": "Link to this ingestion pipeline resource.",
|
||||||
"$ref": "../../../type/basic.json#/definitions/href"
|
"$ref": "../../../type/basic.json#/definitions/href"
|
||||||
|
@ -22,7 +22,7 @@ def get_long_description():
|
|||||||
|
|
||||||
|
|
||||||
base_requirements = {
|
base_requirements = {
|
||||||
"openmetadata-ingestion[airflow-container]~=0.9",
|
"openmetadata-ingestion[airflow-container]~=0.10",
|
||||||
"pendulum~=2.1.2",
|
"pendulum~=2.1.2",
|
||||||
"packaging~=21.2",
|
"packaging~=21.2",
|
||||||
"setuptools~=58.3.0",
|
"setuptools~=58.3.0",
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
from typing import Any, Dict, Optional
|
from typing import Any, Dict, Optional
|
||||||
|
|
||||||
# TODO LOG (just link v1), ENABLE DAG, DISABLE DAG (play pause)
|
# TODO LOG (just link v1)
|
||||||
APIS_METADATA = [
|
APIS_METADATA = [
|
||||||
{
|
{
|
||||||
"name": "deploy_dag",
|
"name": "deploy_dag",
|
||||||
@ -97,6 +97,34 @@ APIS_METADATA = [
|
|||||||
"description": "Get the status of Airflow REST status",
|
"description": "Get the status of Airflow REST status",
|
||||||
"http_method": "GET",
|
"http_method": "GET",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "enable_dag",
|
||||||
|
"description": "Mark the DAG as enabled to run on the next schedule.",
|
||||||
|
"http_method": "POST",
|
||||||
|
"arguments": [],
|
||||||
|
"post_arguments": [
|
||||||
|
{
|
||||||
|
"name": "dag_id",
|
||||||
|
"description": "The id of the dag",
|
||||||
|
"form_input_type": "text",
|
||||||
|
"required": True,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "disable_dag",
|
||||||
|
"description": "Mark the DAG as disabled. It will not run on the next schedule.",
|
||||||
|
"http_method": "POST",
|
||||||
|
"arguments": [],
|
||||||
|
"post_arguments": [
|
||||||
|
{
|
||||||
|
"name": "dag_id",
|
||||||
|
"description": "The id of the dag",
|
||||||
|
"form_input_type": "text",
|
||||||
|
"required": True,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ from openmetadata.api.utils import jwt_token_secure
|
|||||||
from openmetadata.operations.delete import delete_dag_id
|
from openmetadata.operations.delete import delete_dag_id
|
||||||
from openmetadata.operations.deploy import DagDeployer
|
from openmetadata.operations.deploy import DagDeployer
|
||||||
from openmetadata.operations.last_dag_logs import last_dag_logs
|
from openmetadata.operations.last_dag_logs import last_dag_logs
|
||||||
|
from openmetadata.operations.state import disable_dag, enable_dag
|
||||||
from openmetadata.operations.status import status
|
from openmetadata.operations.status import status
|
||||||
from openmetadata.operations.test_connection import test_source_connection
|
from openmetadata.operations.test_connection import test_source_connection
|
||||||
from openmetadata.operations.trigger import trigger
|
from openmetadata.operations.trigger import trigger
|
||||||
@ -133,6 +134,10 @@ class REST_API(AppBuilderBaseView):
|
|||||||
return self.delete_dag()
|
return self.delete_dag()
|
||||||
if api == "last_dag_logs":
|
if api == "last_dag_logs":
|
||||||
return self.last_dag_logs()
|
return self.last_dag_logs()
|
||||||
|
if api == "enable_dag":
|
||||||
|
return self.enable_dag()
|
||||||
|
if api == "disable_dag":
|
||||||
|
return self.disable_dag()
|
||||||
|
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Invalid api param {api}. Expected deploy_dag or trigger_dag."
|
f"Invalid api param {api}. Expected deploy_dag or trigger_dag."
|
||||||
@ -301,3 +306,45 @@ class REST_API(AppBuilderBaseView):
|
|||||||
status=ApiResponse.STATUS_SERVER_ERROR,
|
status=ApiResponse.STATUS_SERVER_ERROR,
|
||||||
error=f"Failed to get last run logs for '{dag_id}' due to {exc} - {traceback.format_exc()}",
|
error=f"Failed to get last run logs for '{dag_id}' due to {exc} - {traceback.format_exc()}",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def enable_dag() -> Response:
|
||||||
|
"""
|
||||||
|
Given a DAG ID, mark the dag as enabled
|
||||||
|
"""
|
||||||
|
request_json = request.get_json()
|
||||||
|
|
||||||
|
dag_id = request_json.get("dag_id")
|
||||||
|
if not dag_id:
|
||||||
|
return ApiResponse.bad_request(f"Missing dag_id argument in the request")
|
||||||
|
|
||||||
|
try:
|
||||||
|
return enable_dag(dag_id)
|
||||||
|
|
||||||
|
except Exception as exc:
|
||||||
|
logging.info(f"Failed to get last run logs for '{dag_id}'")
|
||||||
|
return ApiResponse.error(
|
||||||
|
status=ApiResponse.STATUS_SERVER_ERROR,
|
||||||
|
error=f"Failed to get last run logs for '{dag_id}' due to {exc} - {traceback.format_exc()}",
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def disable_dag() -> Response:
|
||||||
|
"""
|
||||||
|
Given a DAG ID, mark the dag as disabled
|
||||||
|
"""
|
||||||
|
request_json = request.get_json()
|
||||||
|
|
||||||
|
dag_id = request_json.get("dag_id")
|
||||||
|
if not dag_id:
|
||||||
|
return ApiResponse.bad_request(f"Missing dag_id argument in the request")
|
||||||
|
|
||||||
|
try:
|
||||||
|
return disable_dag(dag_id)
|
||||||
|
|
||||||
|
except Exception as exc:
|
||||||
|
logging.info(f"Failed to get last run logs for '{dag_id}'")
|
||||||
|
return ApiResponse.error(
|
||||||
|
status=ApiResponse.STATUS_SERVER_ERROR,
|
||||||
|
error=f"Failed to get last run logs for '{dag_id}' due to {exc} - {traceback.format_exc()}",
|
||||||
|
)
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
# Copyright 2021 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.
|
||||||
|
"""
|
||||||
|
Module containing the logic to toggle DAG state between enabled/disabled
|
||||||
|
"""
|
||||||
|
from airflow import settings
|
||||||
|
from airflow.models import DagModel
|
||||||
|
from flask import Response
|
||||||
|
from openmetadata.api.response import ApiResponse
|
||||||
|
|
||||||
|
|
||||||
|
def _update_dag_state(dag_id: str, paused: bool, message: str) -> Response:
|
||||||
|
"""
|
||||||
|
Given a DAG id, a boolean and a message, update
|
||||||
|
the DAG state between paused or unpaused.
|
||||||
|
:param dag_id: DAG to update
|
||||||
|
:param paused: state to set
|
||||||
|
:param message: message to return
|
||||||
|
:return: API Response
|
||||||
|
"""
|
||||||
|
|
||||||
|
with settings.Session() as session:
|
||||||
|
|
||||||
|
dag_model: DagModel = (
|
||||||
|
session.query(DagModel).filter(DagModel.dag_id == dag_id).first()
|
||||||
|
)
|
||||||
|
|
||||||
|
if not dag_model:
|
||||||
|
return ApiResponse.not_found(f"DAG {dag_id} not found.")
|
||||||
|
|
||||||
|
dag_model.is_paused = paused
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
return ApiResponse.success({"message": message})
|
||||||
|
|
||||||
|
|
||||||
|
def enable_dag(dag_id: str) -> Response:
|
||||||
|
"""
|
||||||
|
Unpause the DAG
|
||||||
|
:param dag_id: DAG to find
|
||||||
|
:return: API Response
|
||||||
|
"""
|
||||||
|
|
||||||
|
return _update_dag_state(
|
||||||
|
dag_id=dag_id, paused=False, message=f"DAG {dag_id} has been enabled"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def disable_dag(dag_id: str) -> Response:
|
||||||
|
"""
|
||||||
|
Pause the DAG
|
||||||
|
:param dag_id: DAG to find
|
||||||
|
:return: API Response
|
||||||
|
"""
|
||||||
|
|
||||||
|
return _update_dag_state(
|
||||||
|
dag_id=dag_id, paused=True, message=f"DAG {dag_id} has been disabled"
|
||||||
|
)
|
Loading…
x
Reference in New Issue
Block a user