openmetadata-ingestion 1.2.4.0__py3-none-any.whl → 1.3.2.0rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of openmetadata-ingestion might be problematic. Click here for more details.
- airflow_provider_openmetadata/lineage/runner.py +44 -5
- airflow_provider_openmetadata/lineage/status.py +1 -1
- metadata/antlr/split_listener.py +1 -4
- metadata/applications/auto_tagger.py +212 -0
- metadata/cli/app.py +47 -0
- metadata/cli/db_dump.py +7 -3
- metadata/clients/aws_client.py +4 -0
- metadata/clients/azure_client.py +85 -0
- metadata/clients/domo_client.py +0 -2
- metadata/cmd.py +24 -13
- metadata/data_insight/processor/reports/cost_analysis_report_data_processor.py +40 -48
- metadata/data_insight/processor/reports/data_processor.py +1 -0
- metadata/data_insight/processor/reports/entity_report_data_processor.py +8 -2
- metadata/data_insight/processor/reports/web_analytic_report_data_processor.py +4 -0
- metadata/data_insight/producer/cost_analysis_producer.py +78 -14
- metadata/data_insight/producer/entity_producer.py +1 -1
- metadata/data_insight/producer/producer_interface.py +1 -1
- metadata/data_insight/producer/web_analytics_producer.py +1 -1
- metadata/data_insight/source/metadata.py +21 -5
- metadata/data_quality/interface/sqlalchemy/databricks/test_suite_interface.py +29 -0
- metadata/data_quality/interface/sqlalchemy/snowflake/test_suite_interface.py +29 -0
- metadata/data_quality/interface/sqlalchemy/sqa_test_suite_interface.py +6 -6
- metadata/data_quality/interface/sqlalchemy/unity_catalog/test_suite_interface.py +35 -0
- metadata/data_quality/interface/test_suite_interface_factory.py +40 -0
- metadata/data_quality/processor/test_case_runner.py +17 -8
- metadata/data_quality/source/test_suite.py +10 -4
- metadata/data_quality/validations/base_test_handler.py +21 -17
- metadata/data_quality/validations/column/base/columnValueLengthsToBeBetween.py +38 -1
- metadata/data_quality/validations/column/base/columnValuesToBeBetween.py +36 -1
- metadata/data_quality/validations/column/base/columnValuesToBeInSet.py +27 -0
- metadata/data_quality/validations/column/base/columnValuesToBeNotInSet.py +27 -0
- metadata/data_quality/validations/column/base/columnValuesToBeNotNull.py +27 -0
- metadata/data_quality/validations/column/base/columnValuesToBeUnique.py +15 -0
- metadata/data_quality/validations/column/base/columnValuesToMatchRegex.py +27 -0
- metadata/data_quality/validations/column/base/columnValuesToNotMatchRegex.py +27 -0
- metadata/data_quality/validations/column/pandas/columnValueLengthsToBeBetween.py +23 -0
- metadata/data_quality/validations/column/pandas/columnValuesToBeBetween.py +23 -0
- metadata/data_quality/validations/column/pandas/columnValuesToBeInSet.py +11 -0
- metadata/data_quality/validations/column/pandas/columnValuesToBeNotInSet.py +11 -0
- metadata/data_quality/validations/column/pandas/columnValuesToBeNotNull.py +11 -0
- metadata/data_quality/validations/column/pandas/columnValuesToMatchRegex.py +11 -0
- metadata/data_quality/validations/column/pandas/columnValuesToNotMatchRegex.py +11 -0
- metadata/data_quality/validations/column/sqlalchemy/columnValueLengthsToBeBetween.py +27 -0
- metadata/data_quality/validations/column/sqlalchemy/columnValuesToBeBetween.py +23 -0
- metadata/data_quality/validations/column/sqlalchemy/columnValuesToBeInSet.py +11 -0
- metadata/data_quality/validations/column/sqlalchemy/columnValuesToBeNotInSet.py +11 -0
- metadata/data_quality/validations/column/sqlalchemy/columnValuesToBeNotNull.py +11 -0
- metadata/data_quality/validations/column/sqlalchemy/columnValuesToMatchRegex.py +11 -0
- metadata/data_quality/validations/column/sqlalchemy/columnValuesToNotMatchRegex.py +11 -0
- metadata/data_quality/validations/mixins/pandas_validator_mixin.py +13 -2
- metadata/data_quality/validations/mixins/sqa_validator_mixin.py +40 -0
- metadata/data_quality/validations/table/base/tableColumnToMatchSet.py +2 -1
- metadata/data_quality/validations/table/pandas/tableColumnToMatchSet.py +2 -1
- metadata/data_quality/validations/table/sqlalchemy/tableColumnToMatchSet.py +7 -2
- metadata/examples/workflows/bigtable.yaml +32 -0
- metadata/examples/workflows/databricks.yaml +0 -1
- metadata/examples/workflows/datalake_azure_default.yaml +29 -0
- metadata/examples/workflows/mongodb.yaml +4 -2
- metadata/examples/workflows/mstr.yaml +24 -0
- metadata/examples/workflows/sas.yaml +28 -0
- metadata/examples/workflows/unity_catalog.yaml +27 -0
- metadata/examples/workflows/unity_catalog_lineage.yaml +18 -0
- metadata/examples/workflows/unity_catalog_usage.yaml +35 -0
- metadata/generated/antlr/EntityLinkLexer.py +425 -292
- metadata/generated/antlr/EntityLinkListener.py +12 -12
- metadata/generated/antlr/EntityLinkParser.py +228 -103
- metadata/generated/schema/analytics/__init__.py +1 -1
- metadata/generated/schema/analytics/basic.py +1 -1
- metadata/generated/schema/analytics/reportData.py +1 -1
- metadata/generated/schema/analytics/reportDataType/__init__.py +1 -1
- metadata/generated/schema/analytics/reportDataType/aggregatedCostAnalysisReportData.py +1 -1
- metadata/generated/schema/analytics/reportDataType/entityReportData.py +1 -1
- metadata/generated/schema/analytics/reportDataType/rawCostAnalysisReportData.py +1 -1
- metadata/generated/schema/analytics/reportDataType/webAnalyticEntityViewReportData.py +1 -1
- metadata/generated/schema/analytics/reportDataType/webAnalyticUserActivityReportData.py +1 -1
- metadata/generated/schema/analytics/webAnalyticEvent.py +1 -1
- metadata/generated/schema/analytics/webAnalyticEventData.py +1 -1
- metadata/generated/schema/analytics/webAnalyticEventType/__init__.py +1 -1
- metadata/generated/schema/analytics/webAnalyticEventType/customEvent.py +1 -1
- metadata/generated/schema/analytics/webAnalyticEventType/pageViewEvent.py +1 -1
- metadata/generated/schema/api/__init__.py +1 -1
- metadata/generated/schema/api/addGlossaryToAssetsRequest.py +1 -1
- metadata/generated/schema/api/analytics/__init__.py +1 -1
- metadata/generated/schema/api/analytics/createWebAnalyticEvent.py +1 -1
- metadata/generated/schema/api/automations/__init__.py +1 -1
- metadata/generated/schema/api/automations/createWorkflow.py +1 -1
- metadata/generated/schema/api/bulkAssets.py +1 -1
- metadata/generated/schema/api/classification/__init__.py +1 -1
- metadata/generated/schema/api/classification/createClassification.py +1 -1
- metadata/generated/schema/api/classification/createTag.py +1 -1
- metadata/generated/schema/api/classification/loadTags.py +1 -1
- metadata/generated/schema/api/createBot.py +2 -3
- metadata/generated/schema/api/createEventPublisherJob.py +2 -2
- metadata/generated/schema/api/createType.py +1 -1
- metadata/generated/schema/api/data/__init__.py +1 -1
- metadata/generated/schema/api/data/createChart.py +1 -1
- metadata/generated/schema/api/data/createContainer.py +2 -2
- metadata/generated/schema/api/data/createCustomProperty.py +7 -12
- metadata/generated/schema/api/data/createDashboard.py +1 -1
- metadata/generated/schema/api/data/createDashboardDataModel.py +1 -1
- metadata/generated/schema/api/data/createDatabase.py +2 -3
- metadata/generated/schema/api/data/createDatabaseSchema.py +2 -3
- metadata/generated/schema/api/data/createGlossary.py +2 -3
- metadata/generated/schema/api/data/createGlossaryTerm.py +2 -3
- metadata/generated/schema/api/data/createMlModel.py +1 -1
- metadata/generated/schema/api/data/createPipeline.py +2 -2
- metadata/generated/schema/api/data/createQuery.py +2 -2
- metadata/generated/schema/api/data/createSearchIndex.py +1 -1
- metadata/generated/schema/api/data/createStoredProcedure.py +2 -4
- metadata/generated/schema/api/data/createTable.py +2 -2
- metadata/generated/schema/api/data/createTableProfile.py +1 -1
- metadata/generated/schema/api/data/createTopic.py +1 -1
- metadata/generated/schema/api/data/loadGlossary.py +1 -1
- metadata/generated/schema/api/data/restoreEntity.py +1 -1
- metadata/generated/schema/api/dataInsight/__init__.py +1 -1
- metadata/generated/schema/api/dataInsight/createDataInsightChart.py +1 -1
- metadata/generated/schema/api/dataInsight/kpi/__init__.py +1 -1
- metadata/generated/schema/api/dataInsight/kpi/createKpiRequest.py +1 -1
- metadata/generated/schema/api/docStore/__init__.py +1 -1
- metadata/generated/schema/api/docStore/createDocument.py +1 -1
- metadata/generated/schema/api/domains/__init__.py +1 -1
- metadata/generated/schema/api/domains/createDataProduct.py +1 -1
- metadata/generated/schema/api/domains/createDomain.py +1 -1
- metadata/generated/schema/api/feed/__init__.py +1 -1
- metadata/generated/schema/api/feed/closeTask.py +8 -1
- metadata/generated/schema/api/feed/createPost.py +1 -1
- metadata/generated/schema/api/feed/createSuggestion.py +30 -0
- metadata/generated/schema/api/feed/createThread.py +5 -1
- metadata/generated/schema/api/feed/resolveTask.py +12 -1
- metadata/generated/schema/api/feed/threadCount.py +18 -14
- metadata/generated/schema/api/lineage/__init__.py +1 -1
- metadata/generated/schema/api/lineage/addLineage.py +1 -1
- metadata/generated/schema/api/openMetadataServerVersion.py +1 -1
- metadata/generated/schema/api/policies/__init__.py +1 -1
- metadata/generated/schema/api/policies/createPolicy.py +1 -1
- metadata/generated/schema/api/services/__init__.py +1 -1
- metadata/generated/schema/api/services/createDashboardService.py +1 -1
- metadata/generated/schema/api/services/createDatabaseService.py +1 -1
- metadata/generated/schema/api/services/createMessagingService.py +1 -1
- metadata/generated/schema/api/services/createMetadataService.py +1 -1
- metadata/generated/schema/api/services/createMlModelService.py +1 -1
- metadata/generated/schema/api/services/createPipelineService.py +1 -1
- metadata/generated/schema/api/services/createSearchService.py +1 -1
- metadata/generated/schema/api/services/createStorageService.py +1 -1
- metadata/generated/schema/api/services/ingestionPipelines/__init__.py +1 -1
- metadata/generated/schema/api/services/ingestionPipelines/createIngestionPipeline.py +1 -1
- metadata/generated/schema/api/setOwner.py +1 -1
- metadata/generated/schema/api/teams/__init__.py +1 -1
- metadata/generated/schema/api/teams/createPersona.py +1 -1
- metadata/generated/schema/api/teams/createRole.py +2 -3
- metadata/generated/schema/api/teams/createTeam.py +1 -1
- metadata/generated/schema/api/teams/createUser.py +2 -2
- metadata/generated/schema/api/tests/__init__.py +1 -1
- metadata/generated/schema/api/tests/createCustomMetric.py +4 -2
- metadata/generated/schema/api/tests/createLogicalTestCases.py +1 -1
- metadata/generated/schema/api/tests/createTestCase.py +4 -1
- metadata/generated/schema/api/tests/createTestCaseResolutionStatus.py +31 -0
- metadata/generated/schema/api/tests/createTestDefinition.py +2 -1
- metadata/generated/schema/api/tests/createTestSuite.py +1 -1
- metadata/generated/schema/api/voteRequest.py +1 -1
- metadata/generated/schema/auth/__init__.py +1 -1
- metadata/generated/schema/auth/basicAuth.py +1 -1
- metadata/generated/schema/auth/basicLoginRequest.py +1 -1
- metadata/generated/schema/auth/changePasswordRequest.py +1 -1
- metadata/generated/schema/auth/createPersonalToken.py +1 -1
- metadata/generated/schema/auth/emailRequest.py +1 -1
- metadata/generated/schema/auth/emailVerificationToken.py +1 -1
- metadata/generated/schema/auth/generateToken.py +1 -1
- metadata/generated/schema/auth/jwtAuth.py +1 -1
- metadata/generated/schema/auth/loginRequest.py +1 -1
- metadata/generated/schema/auth/logoutRequest.py +1 -1
- metadata/generated/schema/auth/passwordResetRequest.py +3 -3
- metadata/generated/schema/auth/passwordResetToken.py +1 -1
- metadata/generated/schema/auth/personalAccessToken.py +1 -1
- metadata/generated/schema/auth/refreshToken.py +1 -1
- metadata/generated/schema/auth/registrationRequest.py +2 -2
- metadata/generated/schema/auth/revokePersonalToken.py +1 -1
- metadata/generated/schema/auth/revokeToken.py +1 -1
- metadata/generated/schema/auth/serviceTokenEnum.py +1 -1
- metadata/generated/schema/auth/ssoAuth.py +1 -1
- metadata/generated/schema/auth/tokenRefreshRequest.py +1 -1
- metadata/generated/schema/configuration/__init__.py +1 -1
- metadata/generated/schema/configuration/appsPrivateConfiguration.py +32 -0
- metadata/generated/schema/configuration/authConfig.py +1 -1
- metadata/generated/schema/configuration/authenticationConfiguration.py +13 -2
- metadata/generated/schema/configuration/authorizerConfiguration.py +1 -1
- metadata/generated/schema/configuration/changeEventConfiguration.py +1 -1
- metadata/generated/schema/configuration/dataQualityConfiguration.py +16 -0
- metadata/generated/schema/configuration/elasticSearchConfiguration.py +7 -1
- metadata/generated/schema/configuration/eventHandlerConfiguration.py +1 -1
- metadata/generated/schema/configuration/fernetConfiguration.py +1 -1
- metadata/generated/schema/configuration/jwtTokenConfiguration.py +1 -1
- metadata/generated/schema/configuration/kafkaEventConfiguration.py +1 -1
- metadata/generated/schema/configuration/ldapConfiguration.py +28 -2
- metadata/generated/schema/configuration/ldapTrustStoreConfig/__init__.py +1 -1
- metadata/generated/schema/configuration/ldapTrustStoreConfig/customTrustManagerConfig.py +1 -1
- metadata/generated/schema/configuration/ldapTrustStoreConfig/hostNameConfig.py +1 -1
- metadata/generated/schema/configuration/ldapTrustStoreConfig/jvmDefaultConfig.py +1 -1
- metadata/generated/schema/configuration/ldapTrustStoreConfig/trustAllConfig.py +1 -1
- metadata/generated/schema/configuration/ldapTrustStoreConfig/truststoreConfig.py +1 -1
- metadata/generated/schema/configuration/loginConfiguration.py +1 -1
- metadata/generated/schema/configuration/logoConfiguration.py +1 -1
- metadata/generated/schema/configuration/pipelineServiceClientConfiguration.py +1 -1
- metadata/generated/schema/configuration/slackAppConfiguration.py +1 -1
- metadata/generated/schema/configuration/taskNotificationConfiguration.py +1 -1
- metadata/generated/schema/configuration/testResultNotificationConfiguration.py +1 -1
- metadata/generated/schema/dataInsight/__init__.py +1 -1
- metadata/generated/schema/dataInsight/dataInsightChart.py +1 -1
- metadata/generated/schema/dataInsight/dataInsightChartResult.py +1 -1
- metadata/generated/schema/dataInsight/kpi/__init__.py +1 -1
- metadata/generated/schema/dataInsight/kpi/basic.py +1 -1
- metadata/generated/schema/dataInsight/kpi/kpi.py +1 -1
- metadata/generated/schema/dataInsight/type/__init__.py +1 -1
- metadata/generated/schema/dataInsight/type/aggregatedUnusedAssetsCount.py +1 -1
- metadata/generated/schema/dataInsight/type/aggregatedUnusedAssetsSize.py +1 -1
- metadata/generated/schema/dataInsight/type/aggregatedUsedVsUnusedAssetsCount.py +1 -1
- metadata/generated/schema/dataInsight/type/aggregatedUsedVsUnusedAssetsSize.py +1 -1
- metadata/generated/schema/dataInsight/type/dailyActiveUsers.py +1 -1
- metadata/generated/schema/dataInsight/type/mostActiveUsers.py +1 -1
- metadata/generated/schema/dataInsight/type/mostViewedEntities.py +1 -1
- metadata/generated/schema/dataInsight/type/pageViewsByEntities.py +1 -1
- metadata/generated/schema/dataInsight/type/percentageOfEntitiesWithDescriptionByType.py +1 -1
- metadata/generated/schema/dataInsight/type/percentageOfEntitiesWithOwnerByType.py +1 -1
- metadata/generated/schema/dataInsight/type/percentageOfServicesWithDescription.py +1 -1
- metadata/generated/schema/dataInsight/type/percentageOfServicesWithOwner.py +1 -1
- metadata/generated/schema/dataInsight/type/totalEntitiesByTier.py +1 -1
- metadata/generated/schema/dataInsight/type/totalEntitiesByType.py +1 -1
- metadata/generated/schema/dataInsight/type/unusedAssets.py +1 -1
- metadata/generated/schema/email/__init__.py +1 -1
- metadata/generated/schema/email/emailRequest.py +1 -1
- metadata/generated/schema/email/smtpSettings.py +1 -1
- metadata/generated/schema/entity/__init__.py +1 -1
- metadata/generated/schema/entity/applications/__init__.py +1 -1
- metadata/generated/schema/entity/applications/app.py +24 -5
- metadata/generated/schema/entity/applications/appRunRecord.py +2 -7
- metadata/generated/schema/entity/applications/configuration/__init__.py +1 -1
- metadata/generated/schema/entity/applications/configuration/applicationConfig.py +30 -0
- metadata/generated/schema/entity/{services/connections/database/mongoDB → applications/configuration/external}/__init__.py +1 -1
- metadata/generated/schema/entity/applications/configuration/external/autoTaggerAppConfig.py +28 -0
- metadata/generated/schema/entity/applications/configuration/external/metaPilotAppConfig.py +46 -0
- metadata/generated/schema/entity/applications/configuration/internal/__init__.py +3 -0
- metadata/generated/schema/entity/applications/configuration/internal/dataInsightsAppConfig.py +14 -0
- metadata/generated/schema/entity/applications/configuration/internal/dataInsightsReportAppConfig.py +27 -0
- metadata/generated/schema/entity/applications/configuration/{searchIndexingApp.py → internal/searchIndexingAppConfig.py} +14 -4
- metadata/generated/schema/entity/applications/configuration/private/external/__init__.py +3 -0
- metadata/generated/schema/entity/applications/configuration/private/external/metaPilotAppPrivateConfig.py +26 -0
- metadata/generated/schema/entity/applications/createAppRequest.py +1 -1
- metadata/generated/schema/entity/applications/jobStatus.py +3 -3
- metadata/generated/schema/entity/applications/liveExecutionContext.py +1 -1
- metadata/generated/schema/entity/applications/marketplace/__init__.py +1 -1
- metadata/generated/schema/entity/applications/marketplace/appMarketPlaceDefinition.py +12 -3
- metadata/generated/schema/entity/applications/marketplace/createAppMarketPlaceDefinitionReq.py +12 -3
- metadata/generated/schema/entity/applications/scheduledExecutionContext.py +1 -1
- metadata/generated/schema/entity/automations/__init__.py +1 -1
- metadata/generated/schema/entity/automations/testServiceConnection.py +2 -2
- metadata/generated/schema/entity/automations/workflow.py +1 -1
- metadata/generated/schema/entity/bot.py +2 -3
- metadata/generated/schema/entity/classification/__init__.py +1 -1
- metadata/generated/schema/entity/classification/classification.py +1 -1
- metadata/generated/schema/entity/classification/tag.py +2 -2
- metadata/generated/schema/entity/data/__init__.py +1 -1
- metadata/generated/schema/entity/data/chart.py +1 -1
- metadata/generated/schema/entity/data/container.py +4 -9
- metadata/generated/schema/entity/data/dashboard.py +1 -1
- metadata/generated/schema/entity/data/dashboardDataModel.py +1 -1
- metadata/generated/schema/entity/data/database.py +4 -8
- metadata/generated/schema/entity/data/databaseSchema.py +2 -8
- metadata/generated/schema/entity/data/glossary.py +1 -1
- metadata/generated/schema/entity/data/glossaryTerm.py +1 -1
- metadata/generated/schema/entity/data/metrics.py +1 -1
- metadata/generated/schema/entity/data/mlmodel.py +2 -2
- metadata/generated/schema/entity/data/pipeline.py +6 -9
- metadata/generated/schema/entity/data/query.py +2 -2
- metadata/generated/schema/entity/data/report.py +1 -1
- metadata/generated/schema/entity/data/searchIndex.py +1 -1
- metadata/generated/schema/entity/data/storedProcedure.py +3 -9
- metadata/generated/schema/entity/data/table.py +18 -12
- metadata/generated/schema/entity/data/topic.py +1 -1
- metadata/generated/schema/entity/docStore/__init__.py +1 -1
- metadata/generated/schema/entity/docStore/document.py +1 -1
- metadata/generated/schema/entity/domains/__init__.py +1 -1
- metadata/generated/schema/entity/domains/dataProduct.py +1 -1
- metadata/generated/schema/entity/domains/domain.py +1 -1
- metadata/generated/schema/entity/events/__init__.py +1 -1
- metadata/generated/schema/entity/events/webhook.py +6 -3
- metadata/generated/schema/entity/feed/__init__.py +1 -1
- metadata/generated/schema/entity/feed/suggestion.py +61 -0
- metadata/generated/schema/entity/feed/thread.py +17 -1
- metadata/generated/schema/entity/policies/__init__.py +1 -1
- metadata/generated/schema/entity/policies/accessControl/__init__.py +1 -1
- metadata/generated/schema/entity/policies/accessControl/resourceDescriptor.py +1 -1
- metadata/generated/schema/entity/policies/accessControl/resourcePermission.py +1 -1
- metadata/generated/schema/entity/policies/accessControl/rule.py +1 -1
- metadata/generated/schema/entity/policies/filters.py +2 -5
- metadata/generated/schema/entity/policies/policy.py +1 -1
- metadata/generated/schema/entity/services/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/common/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/common/sslCertPaths.py +1 -1
- metadata/generated/schema/entity/services/connections/common/sslCertValues.py +1 -1
- metadata/generated/schema/entity/services/connections/common/sslConfig.py +1 -1
- metadata/generated/schema/entity/services/connections/connectionBasicType.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/customDashboardConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/domoDashboardConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/lightdashConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/lookerConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/metabaseConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/modeConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/mstrConnection.py +46 -0
- metadata/generated/schema/entity/services/connections/dashboard/powerBIConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/qlikSenseConnection.py +2 -2
- metadata/generated/schema/entity/services/connections/dashboard/quickSightConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/redashConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/supersetConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/tableauConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/database/athenaConnection.py +2 -2
- metadata/generated/schema/entity/services/connections/database/azureSQLConnection.py +35 -2
- metadata/generated/schema/entity/services/connections/database/bigQueryConnection.py +2 -2
- metadata/generated/schema/entity/services/connections/database/bigTableConnection.py +41 -0
- metadata/generated/schema/entity/services/connections/database/clickhouseConnection.py +2 -2
- metadata/generated/schema/entity/services/connections/database/common/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/database/common/azureConfig.py +20 -0
- metadata/generated/schema/entity/services/connections/database/common/basicAuth.py +1 -1
- metadata/generated/schema/entity/services/connections/database/common/iamAuthConfig.py +1 -1
- metadata/generated/schema/entity/services/connections/database/common/jwtAuth.py +1 -1
- metadata/generated/schema/entity/services/connections/database/couchbaseConnection.py +6 -1
- metadata/generated/schema/entity/services/connections/database/customDatabaseConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/databricksConnection.py +2 -7
- metadata/generated/schema/entity/services/connections/database/datalake/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/database/datalake/azureConfig.py +1 -1
- metadata/generated/schema/entity/services/connections/database/datalake/gcsConfig.py +1 -1
- metadata/generated/schema/entity/services/connections/database/datalake/s3Config.py +1 -1
- metadata/generated/schema/entity/services/connections/database/datalakeConnection.py +2 -2
- metadata/generated/schema/entity/services/connections/database/db2Connection.py +3 -2
- metadata/generated/schema/entity/services/connections/database/deltaLakeConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/domoDatabaseConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/dorisConnection.py +86 -0
- metadata/generated/schema/entity/services/connections/database/druidConnection.py +2 -2
- metadata/generated/schema/entity/services/connections/database/dynamoDBConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/glueConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/greenplumConnection.py +2 -2
- metadata/generated/schema/entity/services/connections/database/hiveConnection.py +2 -2
- metadata/generated/schema/entity/services/connections/database/iceberg/__init__.py +3 -0
- metadata/generated/schema/entity/services/connections/database/iceberg/dynamoDbCatalogConnection.py +17 -0
- metadata/generated/schema/entity/services/connections/database/iceberg/glueCatalogConnection.py +16 -0
- metadata/generated/schema/entity/services/connections/database/iceberg/hiveCatalogConnection.py +23 -0
- metadata/generated/schema/entity/services/connections/database/iceberg/icebergCatalog.py +43 -0
- metadata/generated/schema/entity/services/connections/database/iceberg/icebergFileSystem.py +20 -0
- metadata/generated/schema/entity/services/connections/database/iceberg/restCatalogConnection.py +69 -0
- metadata/generated/schema/entity/services/connections/database/icebergConnection.py +35 -0
- metadata/generated/schema/entity/services/connections/database/impalaConnection.py +2 -2
- metadata/generated/schema/entity/services/connections/database/mariaDBConnection.py +2 -2
- metadata/generated/schema/entity/services/connections/database/mongoDBConnection.py +24 -14
- metadata/generated/schema/entity/services/connections/database/mssqlConnection.py +5 -2
- metadata/generated/schema/entity/services/connections/database/mysqlConnection.py +8 -4
- metadata/generated/schema/entity/services/connections/database/oracleConnection.py +2 -2
- metadata/generated/schema/entity/services/connections/database/pinotDBConnection.py +9 -7
- metadata/generated/schema/entity/services/connections/database/postgresConnection.py +8 -4
- metadata/generated/schema/entity/services/connections/database/prestoConnection.py +2 -2
- metadata/generated/schema/entity/services/connections/database/redshiftConnection.py +2 -2
- metadata/generated/schema/entity/services/connections/database/salesforceConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/sapHana/__init__.py +3 -0
- metadata/generated/schema/entity/services/connections/database/sapHana/sapHanaHDBConnection.py +20 -0
- metadata/generated/schema/entity/services/connections/database/sapHana/sapHanaSQLConnection.py +36 -0
- metadata/generated/schema/entity/services/connections/database/sapHanaConnection.py +7 -41
- metadata/generated/schema/entity/services/connections/database/sasConnection.py +48 -0
- metadata/generated/schema/entity/services/connections/database/singleStoreConnection.py +2 -2
- metadata/generated/schema/entity/services/connections/database/snowflakeConnection.py +2 -2
- metadata/generated/schema/entity/services/connections/database/sqliteConnection.py +2 -2
- metadata/generated/schema/entity/services/connections/database/trinoConnection.py +2 -2
- metadata/generated/schema/entity/services/connections/database/unityCatalogConnection.py +90 -0
- metadata/generated/schema/entity/services/connections/database/verticaConnection.py +2 -2
- metadata/generated/schema/entity/services/connections/messaging/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/messaging/customMessagingConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/messaging/kafkaConnection.py +14 -2
- metadata/generated/schema/entity/services/connections/messaging/kinesisConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/messaging/pulsarConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/messaging/redpandaConnection.py +14 -2
- metadata/generated/schema/entity/services/connections/messaging/saslMechanismType.py +1 -1
- metadata/generated/schema/entity/services/connections/metadata/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/metadata/alationConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/metadata/amundsenConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/metadata/atlasConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/metadata/metadataESConnection.py +2 -2
- metadata/generated/schema/entity/services/connections/metadata/openMetadataConnection.py +5 -20
- metadata/generated/schema/entity/services/connections/mlmodel/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/mlmodel/customMlModelConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/mlmodel/mlflowConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/mlmodel/sageMakerConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/mlmodel/sklearnConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/airbyteConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/airflowConnection.py +2 -8
- metadata/generated/schema/entity/services/connections/pipeline/backendConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/customPipelineConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/dagsterConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/databricksPipelineConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/domoPipelineConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/fivetranConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/gluePipelineConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/nifiConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/sparkConnection.py +23 -0
- metadata/generated/schema/entity/services/connections/pipeline/splineConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/search/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/search/customSearchConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/search/elasticSearch/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/search/elasticSearch/apiAuth.py +1 -1
- metadata/generated/schema/entity/services/connections/search/elasticSearch/basicAuth.py +1 -1
- metadata/generated/schema/entity/services/connections/search/elasticSearchConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/search/openSearchConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/serviceConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/storage/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/storage/{adlsConection.py → adlsConnection.py} +2 -2
- metadata/generated/schema/entity/services/connections/storage/customStorageConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/storage/gcsConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/storage/s3Connection.py +1 -1
- metadata/generated/schema/entity/services/connections/testConnectionDefinition.py +1 -1
- metadata/generated/schema/entity/services/connections/testConnectionResult.py +1 -1
- metadata/generated/schema/entity/services/dashboardService.py +4 -1
- metadata/generated/schema/entity/services/databaseService.py +16 -1
- metadata/generated/schema/entity/services/ingestionPipelines/__init__.py +1 -1
- metadata/generated/schema/entity/services/ingestionPipelines/ingestionPipeline.py +27 -22
- metadata/generated/schema/entity/services/ingestionPipelines/pipelineServiceClientResponse.py +1 -1
- metadata/generated/schema/entity/services/ingestionPipelines/status.py +56 -0
- metadata/generated/schema/entity/services/messagingService.py +1 -1
- metadata/generated/schema/entity/services/metadataService.py +1 -1
- metadata/generated/schema/entity/services/mlmodelService.py +1 -1
- metadata/generated/schema/entity/services/pipelineService.py +4 -1
- metadata/generated/schema/entity/services/searchService.py +1 -1
- metadata/generated/schema/entity/services/serviceType.py +1 -1
- metadata/generated/schema/entity/services/storageService.py +10 -3
- metadata/generated/schema/entity/teams/__init__.py +1 -1
- metadata/generated/schema/entity/teams/persona.py +1 -1
- metadata/generated/schema/entity/teams/role.py +2 -6
- metadata/generated/schema/entity/teams/team.py +1 -1
- metadata/generated/schema/entity/teams/teamHierarchy.py +1 -1
- metadata/generated/schema/entity/teams/user.py +3 -10
- metadata/generated/schema/entity/type.py +4 -19
- metadata/generated/schema/entity/utils/__init__.py +1 -1
- metadata/generated/schema/entity/utils/entitiesCount.py +1 -1
- metadata/generated/schema/entity/utils/servicesCount.py +1 -1
- metadata/generated/schema/entity/utils/supersetApiConnection.py +1 -1
- metadata/generated/schema/events/__init__.py +1 -1
- metadata/generated/schema/events/alertMetrics.py +27 -0
- metadata/generated/schema/events/api/__init__.py +1 -1
- metadata/generated/schema/events/api/createEventSubscription.py +14 -12
- metadata/generated/schema/events/emailAlertConfig.py +1 -1
- metadata/generated/schema/events/eventFilterRule.py +13 -2
- metadata/generated/schema/events/eventSubscription.py +91 -49
- metadata/generated/schema/events/eventSubscriptionOffset.py +21 -0
- metadata/generated/schema/events/failedEvent.py +26 -0
- metadata/generated/schema/events/filterResourceDescriptor.py +27 -0
- metadata/generated/schema/events/subscriptionResourceDescriptor.py +11 -10
- metadata/generated/schema/metadataIngestion/__init__.py +1 -1
- metadata/generated/schema/metadataIngestion/application.py +40 -0
- metadata/generated/schema/metadataIngestion/applicationPipeline.py +15 -6
- metadata/generated/schema/metadataIngestion/dashboardServiceMetadataPipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/dataInsightPipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/databaseServiceMetadataPipeline.py +6 -1
- metadata/generated/schema/metadataIngestion/databaseServiceProfilerPipeline.py +11 -1
- metadata/generated/schema/metadataIngestion/databaseServiceQueryLineagePipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/databaseServiceQueryUsagePipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/dbtPipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/dbtconfig/__init__.py +1 -1
- metadata/generated/schema/metadataIngestion/dbtconfig/dbtAzureConfig.py +6 -3
- metadata/generated/schema/metadataIngestion/dbtconfig/dbtBucketDetails.py +1 -1
- metadata/generated/schema/metadataIngestion/dbtconfig/dbtCloudConfig.py +1 -1
- metadata/generated/schema/metadataIngestion/dbtconfig/dbtGCSConfig.py +6 -3
- metadata/generated/schema/metadataIngestion/dbtconfig/dbtHttpConfig.py +1 -1
- metadata/generated/schema/metadataIngestion/dbtconfig/dbtLocalConfig.py +1 -1
- metadata/generated/schema/metadataIngestion/dbtconfig/dbtS3Config.py +6 -3
- metadata/generated/schema/metadataIngestion/messagingServiceMetadataPipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/metadataToElasticSearchPipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/mlmodelServiceMetadataPipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/pipelineServiceMetadataPipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/searchServiceMetadataPipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/storage/__init__.py +1 -1
- metadata/generated/schema/metadataIngestion/storage/containerMetadataConfig.py +1 -1
- metadata/generated/schema/metadataIngestion/storage/manifestMetadataConfig.py +1 -1
- metadata/generated/schema/metadataIngestion/storage/storageBucketDetails.py +1 -1
- metadata/generated/schema/metadataIngestion/storage/storageMetadataADLSConfig.py +2 -2
- metadata/generated/schema/metadataIngestion/storage/storageMetadataGCSConfig.py +24 -0
- metadata/generated/schema/metadataIngestion/storage/storageMetadataHttpConfig.py +1 -1
- metadata/generated/schema/metadataIngestion/storage/storageMetadataLocalConfig.py +1 -1
- metadata/generated/schema/metadataIngestion/storage/storageMetadataS3Config.py +1 -1
- metadata/generated/schema/metadataIngestion/storageServiceMetadataPipeline.py +8 -1
- metadata/generated/schema/metadataIngestion/testSuitePipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/workflow.py +1 -1
- metadata/generated/schema/monitoring/__init__.py +1 -1
- metadata/generated/schema/monitoring/eventMonitorProvider.py +1 -1
- metadata/generated/schema/security/__init__.py +1 -1
- metadata/generated/schema/security/client/__init__.py +1 -1
- metadata/generated/schema/security/client/auth0SSOClientConfig.py +1 -1
- metadata/generated/schema/security/client/azureSSOClientConfig.py +1 -1
- metadata/generated/schema/security/client/customOidcSSOClientConfig.py +1 -1
- metadata/generated/schema/security/client/googleSSOClientConfig.py +1 -1
- metadata/generated/schema/security/client/oidcClientConfig.py +46 -0
- metadata/generated/schema/security/client/oktaSSOClientConfig.py +1 -1
- metadata/generated/schema/security/client/openMetadataJWTClientConfig.py +1 -1
- metadata/generated/schema/security/client/samlSSOClientConfig.py +1 -1
- metadata/generated/schema/security/credentials/__init__.py +1 -1
- metadata/generated/schema/security/credentials/accessTokenAuth.py +1 -1
- metadata/generated/schema/security/credentials/apiAccessTokenAuth.py +1 -1
- metadata/generated/schema/security/credentials/awsCredentials.py +1 -1
- metadata/generated/schema/security/credentials/azureCredentials.py +21 -9
- metadata/generated/schema/security/credentials/basicAuth.py +1 -1
- metadata/generated/schema/security/credentials/bitbucketCredentials.py +1 -1
- metadata/generated/schema/security/credentials/gcpCredentials.py +7 -3
- metadata/generated/schema/security/credentials/gcpExternalAccount.py +37 -0
- metadata/generated/schema/security/credentials/gcpValues.py +2 -2
- metadata/generated/schema/security/credentials/gitCredentials.py +1 -1
- metadata/generated/schema/security/credentials/githubCredentials.py +1 -1
- metadata/generated/schema/security/secrets/__init__.py +1 -1
- metadata/generated/schema/security/secrets/secretsManagerClientLoader.py +1 -1
- metadata/generated/schema/security/secrets/secretsManagerConfiguration.py +14 -4
- metadata/generated/schema/security/secrets/secretsManagerProvider.py +4 -2
- metadata/generated/schema/security/securityConfiguration.py +1 -1
- metadata/generated/schema/security/ssl/__init__.py +1 -1
- metadata/generated/schema/security/ssl/validateSSLClientConfig.py +1 -1
- metadata/generated/schema/security/ssl/verifySSLConfig.py +4 -1
- metadata/generated/schema/settings/__init__.py +1 -1
- metadata/generated/schema/settings/settings.py +1 -1
- metadata/generated/schema/system/__init__.py +1 -1
- metadata/generated/schema/system/entityError.py +17 -0
- metadata/generated/schema/system/eventPublisherJob.py +5 -19
- metadata/generated/schema/system/indexingError.py +34 -0
- metadata/generated/schema/system/ui/__init__.py +1 -1
- metadata/generated/schema/system/ui/knowledgePanel.py +1 -1
- metadata/generated/schema/system/ui/page.py +1 -1
- metadata/generated/schema/system/validationResponse.py +43 -0
- metadata/generated/schema/tests/__init__.py +1 -1
- metadata/generated/schema/tests/assigned.py +18 -0
- metadata/generated/schema/tests/basic.py +17 -39
- metadata/generated/schema/tests/customMetric.py +4 -2
- metadata/generated/schema/tests/resolved.py +35 -0
- metadata/generated/schema/tests/testCase.py +11 -2
- metadata/generated/schema/tests/testCaseResolutionStatus.py +63 -0
- metadata/generated/schema/tests/testDefinition.py +6 -1
- metadata/generated/schema/tests/testSuite.py +1 -1
- metadata/generated/schema/type/__init__.py +1 -1
- metadata/generated/schema/type/auditLog.py +1 -1
- metadata/generated/schema/type/basic.py +10 -6
- metadata/generated/schema/type/bulkOperationResult.py +1 -1
- metadata/generated/schema/type/changeEvent.py +5 -75
- metadata/generated/schema/type/changeEventType.py +29 -0
- metadata/generated/schema/type/collectionDescriptor.py +1 -1
- metadata/generated/schema/type/csvDocumentation.py +1 -1
- metadata/generated/schema/type/csvErrorType.py +1 -1
- metadata/generated/schema/type/csvFile.py +1 -1
- metadata/generated/schema/type/csvImportResult.py +1 -1
- metadata/generated/schema/type/customProperties/__init__.py +3 -0
- metadata/generated/schema/type/customProperties/enumConfig.py +17 -0
- metadata/generated/schema/type/customProperty.py +52 -0
- metadata/generated/schema/type/dailyCount.py +1 -1
- metadata/generated/schema/type/databaseConnectionConfig.py +1 -1
- metadata/generated/schema/type/entityHistory.py +1 -1
- metadata/generated/schema/type/entityLineage.py +2 -1
- metadata/generated/schema/type/entityReference.py +5 -1
- metadata/generated/schema/type/entityReferenceList.py +1 -1
- metadata/generated/schema/type/entityRelationship.py +1 -1
- metadata/generated/schema/type/entityUsage.py +1 -1
- metadata/generated/schema/type/filterPattern.py +1 -1
- metadata/generated/schema/type/function.py +7 -6
- metadata/generated/schema/type/include.py +1 -1
- metadata/generated/schema/type/jdbcConnection.py +1 -1
- metadata/generated/schema/type/lifeCycle.py +1 -1
- metadata/generated/schema/type/paging.py +1 -1
- metadata/generated/schema/type/profile.py +1 -1
- metadata/generated/schema/type/queryParserData.py +2 -2
- metadata/generated/schema/type/reaction.py +1 -1
- metadata/generated/schema/type/schedule.py +1 -1
- metadata/generated/schema/type/schema.py +1 -1
- metadata/generated/schema/type/tableQuery.py +2 -2
- metadata/generated/schema/type/tableUsageCount.py +1 -1
- metadata/generated/schema/type/tagLabel.py +1 -1
- metadata/generated/schema/type/usageDetails.py +1 -1
- metadata/generated/schema/type/usageRequest.py +1 -1
- metadata/generated/schema/type/votes.py +1 -1
- metadata/great_expectations/action.py +12 -20
- metadata/ingestion/api/delete.py +5 -2
- metadata/ingestion/api/models.py +4 -10
- metadata/ingestion/api/parser.py +3 -37
- metadata/ingestion/api/status.py +15 -4
- metadata/ingestion/api/step.py +39 -6
- metadata/ingestion/api/steps.py +34 -1
- metadata/ingestion/api/topology_runner.py +117 -168
- metadata/ingestion/bulksink/metadata_usage.py +11 -5
- metadata/ingestion/lineage/models.py +4 -0
- metadata/ingestion/lineage/parser.py +28 -12
- metadata/ingestion/lineage/sql_lineage.py +9 -17
- metadata/ingestion/models/custom_properties.py +0 -1
- metadata/ingestion/models/custom_pydantic.py +4 -2
- metadata/ingestion/models/lf_tags_model.py +33 -0
- metadata/ingestion/models/patch_request.py +160 -2
- metadata/ingestion/models/tests_data.py +9 -0
- metadata/ingestion/models/topology.py +177 -60
- metadata/ingestion/ometa/auth_provider.py +0 -349
- metadata/ingestion/ometa/client.py +12 -3
- metadata/ingestion/ometa/mixins/custom_property_mixin.py +11 -11
- metadata/ingestion/ometa/mixins/es_mixin.py +17 -0
- metadata/ingestion/ometa/mixins/patch_mixin.py +21 -72
- metadata/ingestion/ometa/mixins/suggestions_mixin.py +41 -0
- metadata/ingestion/ometa/mixins/table_mixin.py +18 -0
- metadata/ingestion/ometa/mixins/tests_mixin.py +24 -3
- metadata/ingestion/ometa/mixins/user_mixin.py +117 -22
- metadata/ingestion/ometa/ometa_api.py +19 -26
- metadata/ingestion/ometa/routes.py +7 -0
- metadata/ingestion/processor/query_parser.py +9 -2
- metadata/ingestion/sink/metadata_rest.py +29 -8
- metadata/ingestion/source/dashboard/dashboard_service.py +38 -61
- metadata/ingestion/source/dashboard/domodashboard/metadata.py +13 -14
- metadata/ingestion/source/dashboard/lightdash/metadata.py +2 -1
- metadata/ingestion/source/dashboard/looker/metadata.py +41 -29
- metadata/ingestion/source/dashboard/looker/utils.py +4 -2
- metadata/ingestion/source/dashboard/metabase/client.py +4 -0
- metadata/ingestion/source/dashboard/metabase/metadata.py +28 -10
- metadata/ingestion/source/dashboard/metabase/models.py +2 -2
- metadata/ingestion/source/dashboard/mode/client.py +10 -23
- metadata/ingestion/source/dashboard/mode/connection.py +6 -1
- metadata/ingestion/source/dashboard/mode/metadata.py +8 -4
- metadata/ingestion/source/dashboard/mstr/client.py +208 -0
- metadata/ingestion/source/dashboard/mstr/connection.py +53 -0
- metadata/ingestion/source/dashboard/mstr/metadata.py +182 -0
- metadata/ingestion/source/dashboard/mstr/models.py +144 -0
- metadata/ingestion/source/dashboard/powerbi/client.py +4 -1
- metadata/ingestion/source/dashboard/powerbi/metadata.py +15 -10
- metadata/ingestion/source/dashboard/qliksense/metadata.py +11 -7
- metadata/ingestion/source/dashboard/quicksight/metadata.py +9 -5
- metadata/ingestion/source/dashboard/redash/metadata.py +23 -14
- metadata/ingestion/source/dashboard/superset/api_source.py +11 -8
- metadata/ingestion/source/dashboard/superset/client.py +16 -9
- metadata/ingestion/source/dashboard/superset/connection.py +3 -3
- metadata/ingestion/source/dashboard/superset/db_source.py +14 -11
- metadata/ingestion/source/dashboard/superset/mixin.py +22 -18
- metadata/ingestion/source/dashboard/superset/queries.py +1 -1
- metadata/ingestion/source/dashboard/tableau/client.py +91 -11
- metadata/ingestion/source/dashboard/tableau/connection.py +10 -1
- metadata/ingestion/source/dashboard/tableau/metadata.py +76 -70
- metadata/ingestion/source/dashboard/tableau/models.py +0 -8
- metadata/ingestion/source/dashboard/tableau/queries.py +5 -5
- metadata/ingestion/source/database/athena/client.py +80 -0
- metadata/ingestion/source/database/athena/connection.py +7 -0
- metadata/ingestion/source/database/athena/metadata.py +161 -19
- metadata/ingestion/source/database/azuresql/connection.py +21 -3
- metadata/ingestion/source/database/azuresql/metadata.py +0 -1
- metadata/ingestion/source/database/bigquery/connection.py +24 -3
- metadata/ingestion/source/database/bigquery/helper.py +68 -1
- metadata/ingestion/source/database/bigquery/metadata.py +49 -28
- metadata/ingestion/source/database/bigquery/queries.py +33 -4
- metadata/ingestion/source/database/bigquery/query_parser.py +13 -0
- metadata/ingestion/source/database/bigquery/usage.py +1 -3
- metadata/ingestion/source/database/bigtable/client.py +62 -0
- metadata/ingestion/source/database/bigtable/connection.py +116 -0
- metadata/ingestion/source/database/bigtable/metadata.py +224 -0
- metadata/ingestion/source/database/bigtable/models.py +60 -0
- metadata/ingestion/source/database/column_helpers.py +0 -10
- metadata/ingestion/source/database/column_type_parser.py +11 -5
- metadata/ingestion/source/database/common_db_source.py +33 -8
- metadata/ingestion/source/database/common_nosql_source.py +27 -6
- metadata/ingestion/source/database/database_service.py +89 -7
- metadata/ingestion/source/database/databricks/client.py +55 -103
- metadata/ingestion/source/database/databricks/connection.py +16 -55
- metadata/ingestion/source/database/databricks/lineage.py +29 -26
- metadata/ingestion/source/database/databricks/metadata.py +534 -11
- metadata/ingestion/source/database/databricks/queries.py +27 -0
- metadata/ingestion/source/database/databricks/query_parser.py +5 -1
- metadata/ingestion/source/database/databricks/usage.py +3 -3
- metadata/ingestion/source/database/datalake/connection.py +33 -18
- metadata/ingestion/source/database/datalake/metadata.py +113 -27
- metadata/ingestion/source/database/dbt/dbt_config.py +7 -14
- metadata/ingestion/source/database/dbt/dbt_service.py +10 -14
- metadata/ingestion/source/database/dbt/dbt_utils.py +3 -1
- metadata/ingestion/source/database/dbt/metadata.py +27 -53
- metadata/ingestion/source/database/deltalake/metadata.py +6 -3
- metadata/ingestion/source/database/domodatabase/metadata.py +7 -6
- metadata/ingestion/source/database/doris/connection.py +72 -0
- metadata/ingestion/source/database/doris/metadata.py +315 -0
- metadata/ingestion/source/database/doris/queries.py +54 -0
- metadata/ingestion/source/database/doris/utils.py +64 -0
- metadata/ingestion/source/database/extended_sample_data.py +532 -0
- metadata/ingestion/source/database/glue/metadata.py +8 -5
- metadata/ingestion/source/database/hive/connection.py +0 -2
- metadata/ingestion/source/database/hive/utils.py +3 -0
- metadata/ingestion/source/database/iceberg/catalog/__init__.py +65 -0
- metadata/ingestion/source/database/iceberg/catalog/base.py +40 -0
- metadata/ingestion/source/database/iceberg/catalog/dynamodb.py +102 -0
- metadata/ingestion/source/database/iceberg/catalog/glue.py +88 -0
- metadata/ingestion/source/database/iceberg/catalog/hive.py +51 -0
- metadata/ingestion/source/database/iceberg/catalog/rest.py +84 -0
- metadata/ingestion/source/database/iceberg/connection.py +68 -0
- metadata/ingestion/source/database/iceberg/fs/__init__.py +52 -0
- metadata/ingestion/source/database/iceberg/fs/azure.py +44 -0
- metadata/ingestion/source/database/iceberg/fs/base.py +30 -0
- metadata/ingestion/source/database/iceberg/fs/s3.py +77 -0
- metadata/ingestion/source/database/iceberg/helper.py +124 -0
- metadata/ingestion/source/database/iceberg/metadata.py +311 -0
- metadata/ingestion/source/database/iceberg/models.py +66 -0
- metadata/ingestion/source/database/life_cycle_query_mixin.py +72 -3
- metadata/ingestion/source/database/mongodb/connection.py +1 -5
- metadata/ingestion/source/database/mssql/lineage.py +3 -0
- metadata/ingestion/source/database/mssql/metadata.py +108 -4
- metadata/ingestion/source/database/mssql/models.py +30 -0
- metadata/ingestion/source/database/mssql/queries.py +178 -1
- metadata/ingestion/source/database/mssql/usage.py +5 -1
- metadata/ingestion/source/database/mssql/utils.py +207 -4
- metadata/ingestion/source/database/mysql/connection.py +14 -0
- metadata/ingestion/source/database/mysql/metadata.py +0 -2
- metadata/ingestion/source/database/oracle/metadata.py +108 -2
- metadata/ingestion/source/database/oracle/models.py +30 -0
- metadata/ingestion/source/database/oracle/queries.py +99 -18
- metadata/ingestion/source/database/oracle/utils.py +0 -1
- metadata/ingestion/source/database/postgres/connection.py +15 -0
- metadata/ingestion/source/database/postgres/lineage.py +32 -14
- metadata/ingestion/source/database/postgres/metadata.py +15 -7
- metadata/ingestion/source/database/postgres/pgspider/lineage.py +0 -1
- metadata/ingestion/source/database/postgres/queries.py +4 -2
- metadata/ingestion/source/database/postgres/query_parser.py +4 -72
- metadata/ingestion/source/database/postgres/usage.py +41 -0
- metadata/ingestion/source/database/postgres/utils.py +34 -0
- metadata/ingestion/source/database/query_parser_source.py +8 -2
- metadata/ingestion/source/database/redshift/metadata.py +14 -4
- metadata/ingestion/source/database/redshift/queries.py +10 -4
- metadata/ingestion/source/database/redshift/query_parser.py +16 -0
- metadata/ingestion/source/database/redshift/usage.py +0 -2
- metadata/ingestion/source/database/salesforce/metadata.py +32 -3
- metadata/ingestion/source/database/sample_data.py +120 -6
- metadata/ingestion/source/database/sas/client.py +184 -0
- metadata/ingestion/source/database/sas/connection.py +47 -0
- metadata/ingestion/source/database/sas/extension_attr.py +103 -0
- metadata/ingestion/source/database/sas/metadata.py +914 -0
- metadata/ingestion/source/database/snowflake/metadata.py +34 -48
- metadata/ingestion/source/database/snowflake/models.py +6 -1
- metadata/ingestion/source/database/snowflake/queries.py +6 -4
- metadata/ingestion/source/database/snowflake/query_parser.py +5 -20
- metadata/ingestion/source/database/snowflake/utils.py +23 -8
- metadata/ingestion/source/database/stored_procedures_mixin.py +12 -8
- metadata/ingestion/source/database/unitycatalog/__init__.py +0 -0
- metadata/ingestion/source/database/unitycatalog/client.py +87 -0
- metadata/ingestion/source/database/unitycatalog/connection.py +97 -0
- metadata/ingestion/source/database/{databricks/unity_catalog → unitycatalog}/lineage.py +11 -11
- metadata/ingestion/source/database/{databricks/unity_catalog → unitycatalog}/metadata.py +42 -49
- metadata/ingestion/source/database/unitycatalog/query_parser.py +60 -0
- metadata/ingestion/source/database/unitycatalog/usage.py +31 -0
- metadata/ingestion/source/database/usage_source.py +3 -2
- metadata/ingestion/source/messaging/common_broker_source.py +15 -11
- metadata/ingestion/source/messaging/kafka/connection.py +45 -4
- metadata/ingestion/source/messaging/kinesis/metadata.py +6 -3
- metadata/ingestion/source/messaging/messaging_service.py +6 -2
- metadata/ingestion/source/metadata/amundsen/metadata.py +10 -7
- metadata/ingestion/source/metadata/atlas/metadata.py +5 -5
- metadata/ingestion/source/mlmodel/mlflow/metadata.py +5 -2
- metadata/ingestion/source/mlmodel/mlmodel_service.py +6 -2
- metadata/ingestion/source/mlmodel/sagemaker/metadata.py +20 -8
- metadata/ingestion/source/pipeline/airflow/connection.py +0 -12
- metadata/ingestion/source/pipeline/airflow/lineage_parser.py +12 -6
- metadata/ingestion/source/pipeline/airflow/metadata.py +63 -34
- metadata/ingestion/source/pipeline/airflow/models.py +5 -4
- metadata/ingestion/source/pipeline/dagster/metadata.py +7 -4
- metadata/ingestion/source/pipeline/databrickspipeline/connection.py +1 -5
- metadata/ingestion/source/pipeline/databrickspipeline/metadata.py +14 -11
- metadata/ingestion/source/pipeline/domopipeline/metadata.py +7 -4
- metadata/ingestion/source/pipeline/gluepipeline/metadata.py +5 -2
- metadata/ingestion/source/pipeline/pipeline_service.py +6 -2
- metadata/ingestion/source/pipeline/spline/metadata.py +0 -1
- metadata/ingestion/source/search/elasticsearch/connection.py +4 -1
- metadata/ingestion/source/search/elasticsearch/metadata.py +1 -2
- metadata/ingestion/source/search/search_service.py +6 -2
- metadata/ingestion/source/storage/s3/metadata.py +22 -17
- metadata/ingestion/source/storage/storage_service.py +53 -11
- metadata/ingestion/stage/table_usage.py +9 -2
- metadata/mixins/sqalchemy/sqa_mixin.py +14 -7
- metadata/parsers/protobuf_parser.py +29 -11
- metadata/pii/processor.py +9 -2
- metadata/pii/scanners/ner_scanner.py +5 -3
- metadata/profiler/api/models.py +19 -1
- metadata/profiler/interface/pandas/profiler_interface.py +59 -18
- metadata/profiler/interface/profiler_interface.py +14 -4
- metadata/profiler/interface/profiler_interface_factory.py +49 -14
- metadata/profiler/interface/sqlalchemy/bigquery/profiler_interface.py +3 -0
- metadata/profiler/interface/sqlalchemy/databricks/profiler_interface.py +26 -0
- metadata/profiler/interface/sqlalchemy/db2/__init__.py +0 -0
- metadata/profiler/interface/sqlalchemy/db2/profiler_interface.py +38 -0
- metadata/profiler/interface/sqlalchemy/mariadb/profiler_interface.py +85 -0
- metadata/profiler/interface/sqlalchemy/profiler_interface.py +77 -34
- metadata/profiler/interface/sqlalchemy/single_store/profiler_interface.py +2 -2
- metadata/profiler/interface/sqlalchemy/snowflake/profiler_interface.py +7 -0
- metadata/profiler/interface/sqlalchemy/trino/profiler_interface.py +2 -2
- metadata/profiler/interface/sqlalchemy/unity_catalog/profiler_interface.py +33 -0
- metadata/profiler/metrics/composed/null_ratio.py +1 -1
- metadata/profiler/metrics/hybrid/histogram.py +1 -0
- metadata/profiler/metrics/static/max.py +4 -1
- metadata/profiler/metrics/static/min.py +4 -1
- metadata/profiler/metrics/system/queries/snowflake.py +89 -17
- metadata/profiler/metrics/system/system.py +62 -20
- metadata/profiler/orm/functions/conn_test.py +1 -0
- metadata/profiler/orm/functions/length.py +1 -0
- metadata/profiler/orm/functions/median.py +9 -1
- metadata/profiler/orm/functions/sum.py +1 -0
- metadata/profiler/orm/functions/table_metric_computer.py +462 -0
- metadata/profiler/orm/registry.py +2 -0
- metadata/profiler/processor/core.py +129 -62
- metadata/profiler/processor/default.py +14 -3
- metadata/profiler/processor/handle_partition.py +2 -2
- metadata/profiler/processor/processor.py +10 -7
- metadata/profiler/processor/sample_data_handler.py +6 -2
- metadata/profiler/processor/sampler/sqlalchemy/bigquery/sampler.py +31 -3
- metadata/profiler/processor/sampler/sqlalchemy/sampler.py +29 -6
- metadata/profiler/processor/sampler/sqlalchemy/trino/sampler.py +10 -4
- metadata/profiler/source/base/profiler_source.py +5 -2
- metadata/profiler/source/bigquery/type_mapper.py +0 -1
- metadata/profiler/source/databricks/profiler_source.py +36 -0
- metadata/profiler/source/mariadb/functions/median.py +20 -0
- metadata/profiler/source/mariadb/metrics/window/first_quartile.py +10 -0
- metadata/profiler/source/mariadb/metrics/window/median.py +10 -0
- metadata/profiler/source/mariadb/metrics/window/third_quartile.py +10 -0
- metadata/profiler/source/metadata.py +49 -10
- metadata/profiler/source/metadata_ext.py +16 -50
- metadata/profiler/source/profiler_source_factory.py +8 -0
- metadata/py.typed +0 -0
- metadata/readers/dataframe/json.py +5 -4
- metadata/readers/file/api_reader.py +0 -1
- metadata/utils/constants.py +5 -0
- metadata/utils/credentials.py +36 -19
- metadata/utils/datalake/datalake_utils.py +369 -129
- metadata/utils/entity_link.py +26 -6
- metadata/utils/execution_time_tracker.py +199 -0
- metadata/utils/filters.py +4 -0
- metadata/utils/fqn.py +20 -0
- metadata/utils/helpers.py +34 -39
- metadata/utils/importer.py +2 -3
- metadata/utils/life_cycle_utils.py +4 -4
- metadata/utils/logger.py +13 -2
- metadata/utils/partition.py +10 -5
- metadata/utils/secrets/aws_based_secrets_manager.py +67 -4
- metadata/utils/secrets/aws_secrets_manager.py +7 -2
- metadata/utils/secrets/aws_ssm_secrets_manager.py +7 -2
- metadata/utils/secrets/azure_kv_secrets_manager.py +132 -0
- metadata/utils/secrets/{noop_secrets_manager.py → db_secrets_manager.py} +4 -3
- metadata/utils/secrets/external_secrets_manager.py +25 -3
- metadata/utils/secrets/secrets_manager_factory.py +15 -33
- metadata/utils/{source_hash_utils.py → source_hash.py} +10 -1
- metadata/utils/sqlalchemy_utils.py +21 -0
- metadata/utils/storage_metadata_config.py +42 -14
- metadata/utils/tag_utils.py +5 -2
- metadata/workflow/application.py +154 -0
- metadata/workflow/application_output_handler.py +34 -0
- metadata/workflow/base.py +88 -153
- metadata/workflow/data_insight.py +8 -7
- metadata/workflow/data_quality.py +3 -2
- metadata/workflow/ingestion.py +203 -0
- metadata/workflow/metadata.py +2 -3
- metadata/workflow/output_handler.py +226 -0
- metadata/workflow/profiler.py +2 -2
- metadata/workflow/usage.py +3 -4
- metadata/workflow/workflow_output_handler.py +15 -255
- metadata/workflow/workflow_status_mixin.py +44 -52
- openmetadata_ingestion-1.3.2.0rc1.dist-info/METADATA +758 -0
- {openmetadata_ingestion-1.2.4.0.dist-info → openmetadata_ingestion-1.3.2.0rc1.dist-info}/RECORD +870 -762
- {openmetadata_ingestion-1.2.4.0.dist-info → openmetadata_ingestion-1.3.2.0rc1.dist-info}/WHEEL +1 -1
- metadata/generated/schema/entity/applications/appConfig.py +0 -21
- metadata/generated/schema/entity/applications/configuration/dataInsightsApp.py +0 -17
- metadata/generated/schema/entity/applications/configuration/externalAppIngestionConfig.py +0 -38
- metadata/generated/schema/entity/services/connections/database/mongoDB/mongoDBValues.py +0 -44
- metadata/generated/schema/events/dataInsightAlertConfig.py +0 -17
- metadata/generated/schema/events/entitySpelFilters.py +0 -19
- metadata/ingestion/models/es_documents.py +0 -339
- metadata/ingestion/ometa/mixins/glossary_mixin.py +0 -501
- metadata/ingestion/ometa/provider_registry.py +0 -144
- metadata/ingestion/source/database/databricks/legacy/lineage.py +0 -51
- metadata/ingestion/source/database/databricks/legacy/metadata.py +0 -339
- metadata/ingestion/source/metadata/metadata_elasticsearch/metadata.py +0 -144
- metadata/profiler/orm/functions/table_metric_construct.py +0 -365
- metadata/utils/secrets/client/loader.py +0 -78
- openmetadata_ingestion-1.2.4.0.dist-info/METADATA +0 -429
- /metadata/examples/workflows/{datalake_azure.yaml → datalake_azure_client_secret.yaml} +0 -0
- /metadata/ingestion/source/{database/databricks/legacy → dashboard/mstr}/__init__.py +0 -0
- /metadata/ingestion/source/database/{databricks/unity_catalog → bigtable}/__init__.py +0 -0
- /metadata/ingestion/source/{metadata/metadata_elasticsearch → database/doris}/__init__.py +0 -0
- /metadata/{utils/secrets/client → ingestion/source/database/sas}/__init__.py +0 -0
- /metadata/ingestion/source/database/{databricks → unitycatalog}/models.py +0 -0
- {openmetadata_ingestion-1.2.4.0.dist-info → openmetadata_ingestion-1.3.2.0rc1.dist-info}/LICENSE +0 -0
- {openmetadata_ingestion-1.2.4.0.dist-info → openmetadata_ingestion-1.3.2.0rc1.dist-info}/entry_points.txt +0 -0
- {openmetadata_ingestion-1.2.4.0.dist-info → openmetadata_ingestion-1.3.2.0rc1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,914 @@
|
|
|
1
|
+
# Copyright 2021 Collate
|
|
2
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
# you may not use this file except in compliance with the License.
|
|
4
|
+
# You may obtain a copy of the License at
|
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
7
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
8
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
9
|
+
# See the License for the specific language governing permissions and
|
|
10
|
+
# limitations under the License.
|
|
11
|
+
|
|
12
|
+
"""
|
|
13
|
+
SAS source to extract metadata
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
# pylint: disable=protected-access,too-many-branches,too-many-locals
|
|
17
|
+
import copy
|
|
18
|
+
import json
|
|
19
|
+
import re
|
|
20
|
+
import time
|
|
21
|
+
import traceback
|
|
22
|
+
from typing import Any, Iterable, Optional, Tuple, Union
|
|
23
|
+
|
|
24
|
+
from requests.exceptions import HTTPError
|
|
25
|
+
|
|
26
|
+
from metadata.generated.schema.api.data.createDashboard import CreateDashboardRequest
|
|
27
|
+
from metadata.generated.schema.api.data.createDatabase import CreateDatabaseRequest
|
|
28
|
+
from metadata.generated.schema.api.data.createDatabaseSchema import (
|
|
29
|
+
CreateDatabaseSchemaRequest,
|
|
30
|
+
)
|
|
31
|
+
from metadata.generated.schema.api.data.createQuery import CreateQueryRequest
|
|
32
|
+
from metadata.generated.schema.api.data.createStoredProcedure import (
|
|
33
|
+
CreateStoredProcedureRequest,
|
|
34
|
+
)
|
|
35
|
+
from metadata.generated.schema.api.data.createTable import CreateTableRequest
|
|
36
|
+
from metadata.generated.schema.api.data.createTableProfile import (
|
|
37
|
+
CreateTableProfileRequest,
|
|
38
|
+
)
|
|
39
|
+
from metadata.generated.schema.api.lineage.addLineage import AddLineageRequest
|
|
40
|
+
from metadata.generated.schema.api.services.createDashboardService import (
|
|
41
|
+
CreateDashboardServiceRequest,
|
|
42
|
+
)
|
|
43
|
+
from metadata.generated.schema.entity.data.dashboard import Dashboard
|
|
44
|
+
from metadata.generated.schema.entity.data.database import Database
|
|
45
|
+
from metadata.generated.schema.entity.data.table import (
|
|
46
|
+
Column,
|
|
47
|
+
ColumnProfile,
|
|
48
|
+
Table,
|
|
49
|
+
TableProfile,
|
|
50
|
+
)
|
|
51
|
+
from metadata.generated.schema.entity.services.connections.dashboard.customDashboardConnection import (
|
|
52
|
+
CustomDashboardConnection,
|
|
53
|
+
CustomDashboardType,
|
|
54
|
+
)
|
|
55
|
+
from metadata.generated.schema.entity.services.connections.database.sasConnection import (
|
|
56
|
+
SASConnection,
|
|
57
|
+
)
|
|
58
|
+
from metadata.generated.schema.entity.services.dashboardService import (
|
|
59
|
+
DashboardConnection,
|
|
60
|
+
DashboardServiceType,
|
|
61
|
+
)
|
|
62
|
+
from metadata.generated.schema.metadataIngestion.databaseServiceMetadataPipeline import (
|
|
63
|
+
DatabaseServiceMetadataPipeline,
|
|
64
|
+
)
|
|
65
|
+
from metadata.generated.schema.metadataIngestion.workflow import (
|
|
66
|
+
Source as WorkflowSource,
|
|
67
|
+
)
|
|
68
|
+
from metadata.generated.schema.type.entityLineage import EntitiesEdge
|
|
69
|
+
from metadata.generated.schema.type.entityReference import EntityReference
|
|
70
|
+
from metadata.ingestion.api.common import Entity
|
|
71
|
+
from metadata.ingestion.api.models import Either, StackTraceError
|
|
72
|
+
from metadata.ingestion.api.steps import InvalidSourceException
|
|
73
|
+
from metadata.ingestion.models.ometa_classification import OMetaTagAndClassification
|
|
74
|
+
from metadata.ingestion.ometa.ometa_api import OpenMetadata
|
|
75
|
+
from metadata.ingestion.source.connections import get_connection, get_test_connection_fn
|
|
76
|
+
from metadata.ingestion.source.database.column_type_parser import ColumnTypeParser
|
|
77
|
+
from metadata.ingestion.source.database.database_service import DatabaseServiceSource
|
|
78
|
+
from metadata.ingestion.source.database.sas.client import SASClient
|
|
79
|
+
from metadata.ingestion.source.database.sas.extension_attr import TABLE_CUSTOM_ATTR
|
|
80
|
+
from metadata.utils import fqn
|
|
81
|
+
from metadata.utils.logger import ingestion_logger
|
|
82
|
+
|
|
83
|
+
logger = ingestion_logger()
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class SasSource(
|
|
87
|
+
DatabaseServiceSource
|
|
88
|
+
): # pylint: disable=too-many-instance-attributes,too-many-public-methods
|
|
89
|
+
"""
|
|
90
|
+
Implements the necessary methods to extract
|
|
91
|
+
Database metadata from SAS Database Source
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
config: WorkflowSource
|
|
95
|
+
sas_client: SASClient
|
|
96
|
+
|
|
97
|
+
def __init__(self, config: WorkflowSource, metadata: OpenMetadata):
|
|
98
|
+
super().__init__()
|
|
99
|
+
self.config = config
|
|
100
|
+
self.metadata = metadata
|
|
101
|
+
self.source_config: DatabaseServiceMetadataPipeline = (
|
|
102
|
+
self.config.sourceConfig.config
|
|
103
|
+
)
|
|
104
|
+
self.service_connection = self.config.serviceConnection.__root__.config
|
|
105
|
+
|
|
106
|
+
self.sas_client = get_connection(self.service_connection)
|
|
107
|
+
self.connection_obj = self.sas_client
|
|
108
|
+
self.test_connection()
|
|
109
|
+
|
|
110
|
+
self.db_service_name = self.config.serviceName
|
|
111
|
+
self.db_name = None
|
|
112
|
+
self.db_schema_name = None
|
|
113
|
+
self.table_fqns = []
|
|
114
|
+
|
|
115
|
+
self.dashboard_service_name = None
|
|
116
|
+
self.chart_names = None
|
|
117
|
+
self.report_description = None
|
|
118
|
+
|
|
119
|
+
self.add_table_custom_attributes()
|
|
120
|
+
|
|
121
|
+
self.databases = None
|
|
122
|
+
self.database_schemas = None
|
|
123
|
+
|
|
124
|
+
@classmethod
|
|
125
|
+
def create(cls, config_dict: dict, metadata: OpenMetadata):
|
|
126
|
+
logger.info(f"running create {config_dict}")
|
|
127
|
+
config: WorkflowSource = WorkflowSource.parse_obj(config_dict)
|
|
128
|
+
connection: SASConnection = config.serviceConnection.__root__.config
|
|
129
|
+
if not isinstance(connection, SASConnection):
|
|
130
|
+
raise InvalidSourceException(
|
|
131
|
+
f"Expected SASConnection, but got {connection}"
|
|
132
|
+
)
|
|
133
|
+
return cls(config, metadata)
|
|
134
|
+
|
|
135
|
+
def _iter(self) -> Iterable[Either[Entity]]:
|
|
136
|
+
# For debug purpose (when ingesting locally)
|
|
137
|
+
# yield Either(
|
|
138
|
+
# right=self.metadata.get_create_service_from_source(
|
|
139
|
+
# entity=DatabaseService, config=self.config
|
|
140
|
+
# )
|
|
141
|
+
# )
|
|
142
|
+
|
|
143
|
+
# create tables from sas dataSets
|
|
144
|
+
if self.sas_client.enable_datatables:
|
|
145
|
+
for table in self.sas_client.list_assets("datasets"):
|
|
146
|
+
yield from self.create_table_entity(table)
|
|
147
|
+
|
|
148
|
+
if self.sas_client.enable_reports:
|
|
149
|
+
yield from self.create_dashboard_service("SAS_reports")
|
|
150
|
+
for report in self.sas_client.list_assets("reports"):
|
|
151
|
+
yield from self.process_report(report)
|
|
152
|
+
|
|
153
|
+
if self.sas_client.enable_dataflows:
|
|
154
|
+
yield from self.create_dashboard_service("SAS_dataFlows")
|
|
155
|
+
for data_flow in self.sas_client.list_assets("dataflows"):
|
|
156
|
+
yield from self.process_dataflow(data_flow)
|
|
157
|
+
|
|
158
|
+
def process_report(self, report):
|
|
159
|
+
self.table_fqns = []
|
|
160
|
+
logger.info(f"Ingesting report: {report}")
|
|
161
|
+
report_instance = self.sas_client.get_instance(report["id"])
|
|
162
|
+
for table in self.get_report_tables(
|
|
163
|
+
report_instance["resourceId"].split("/")[-1]
|
|
164
|
+
):
|
|
165
|
+
yield from self.create_table_entity(table)
|
|
166
|
+
yield from self.create_report_entity(report_instance)
|
|
167
|
+
|
|
168
|
+
def process_dataflow(self, data_flow):
|
|
169
|
+
"""
|
|
170
|
+
Process dataflow assets
|
|
171
|
+
"""
|
|
172
|
+
self.table_fqns = []
|
|
173
|
+
logger.info(f"Ingesting dataflow: {data_flow}")
|
|
174
|
+
data_flow_instance = self.sas_client.get_instance(data_flow["id"])
|
|
175
|
+
if not data_flow_instance.get("relationships"):
|
|
176
|
+
logger.warning(f"No relationships are found for {data_flow['name']}")
|
|
177
|
+
return
|
|
178
|
+
input_asset_ids = [
|
|
179
|
+
rel["endpointId"]
|
|
180
|
+
for rel in data_flow_instance["relationships"]
|
|
181
|
+
if rel["definitionId"] == "6179884b-91ec-4236-ad6b-52c7f454f217"
|
|
182
|
+
]
|
|
183
|
+
output_asset_ids = [
|
|
184
|
+
rel["endpointId"]
|
|
185
|
+
for rel in data_flow_instance["relationships"]
|
|
186
|
+
if rel["definitionId"] == "e1349270-fdbb-4231-9841-79917a307471"
|
|
187
|
+
]
|
|
188
|
+
for input_asset in (self.sas_client.get_instance(id) for id in input_asset_ids):
|
|
189
|
+
yield from self.create_table_entity(input_asset)
|
|
190
|
+
input_fqns = copy.deepcopy(self.table_fqns)
|
|
191
|
+
self.table_fqns = []
|
|
192
|
+
for output_asset in (
|
|
193
|
+
self.sas_client.get_instance(id) for id in output_asset_ids
|
|
194
|
+
):
|
|
195
|
+
yield from self.create_table_entity(output_asset)
|
|
196
|
+
yield from self.create_data_flow_entity(
|
|
197
|
+
data_flow_instance, input_fqns, copy.deepcopy(self.table_fqns)
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
def create_database_alt(self, db):
|
|
201
|
+
"""
|
|
202
|
+
Find the name of the mock DB service
|
|
203
|
+
Use the link to the parent of the resourceId of the datastore itself, and use its name
|
|
204
|
+
Then the db service name will be the provider id
|
|
205
|
+
"""
|
|
206
|
+
data_store_endpoint = db["resourceId"][1:]
|
|
207
|
+
logger.info(f"{data_store_endpoint}")
|
|
208
|
+
data_store_resource = self.sas_client.get_data_source(data_store_endpoint)
|
|
209
|
+
|
|
210
|
+
data_store_parent_endpoint = ""
|
|
211
|
+
for link in data_store_resource["links"]:
|
|
212
|
+
if link["rel"] == "parent":
|
|
213
|
+
data_store_parent_endpoint = link["uri"][1:]
|
|
214
|
+
break
|
|
215
|
+
|
|
216
|
+
data_store_parent = self.sas_client.get_data_source(data_store_parent_endpoint)
|
|
217
|
+
self.db_name = data_store_parent["id"]
|
|
218
|
+
database = CreateDatabaseRequest(
|
|
219
|
+
name=data_store_parent["id"],
|
|
220
|
+
displayName=data_store_parent["name"],
|
|
221
|
+
service=self.db_service_name,
|
|
222
|
+
)
|
|
223
|
+
database_entity = self.metadata.create_or_update(data=database)
|
|
224
|
+
return database_entity
|
|
225
|
+
|
|
226
|
+
def create_database_schema(self, table):
|
|
227
|
+
"""
|
|
228
|
+
create database schema
|
|
229
|
+
"""
|
|
230
|
+
try:
|
|
231
|
+
context = table["resourceId"].split("/")[3]
|
|
232
|
+
|
|
233
|
+
provider = context.split("~")[0]
|
|
234
|
+
self.db_name = provider + "." + context.split("~")[2]
|
|
235
|
+
self.db_schema_name = context.split("~")[4]
|
|
236
|
+
|
|
237
|
+
database = CreateDatabaseRequest(
|
|
238
|
+
name=self.db_name,
|
|
239
|
+
displayName=self.db_name,
|
|
240
|
+
service=self.config.serviceName,
|
|
241
|
+
)
|
|
242
|
+
database = self.metadata.create_or_update(data=database)
|
|
243
|
+
|
|
244
|
+
db_schema = CreateDatabaseSchemaRequest(
|
|
245
|
+
name=self.db_schema_name, database=database.fullyQualifiedName
|
|
246
|
+
)
|
|
247
|
+
db_schema_entity = self.metadata.create_or_update(db_schema)
|
|
248
|
+
return db_schema_entity
|
|
249
|
+
|
|
250
|
+
except HTTPError as _:
|
|
251
|
+
# Find the "database" entity in Information Catalog
|
|
252
|
+
# First see if the table is a member of the library through the relationships attribute
|
|
253
|
+
# Or we could use views to query the dataStores
|
|
254
|
+
data_store_data_sets = "4b114f6e-1c2a-4060-9184-6809a612f27b"
|
|
255
|
+
data_store_id = None
|
|
256
|
+
for relation in table["relationships"]:
|
|
257
|
+
if relation["definitionId"] != data_store_data_sets:
|
|
258
|
+
continue
|
|
259
|
+
data_store_id = relation["endpointId"]
|
|
260
|
+
break
|
|
261
|
+
|
|
262
|
+
if data_store_id is None:
|
|
263
|
+
# log error due to exclude amount of work with tables in dataTables
|
|
264
|
+
logger.error("Data store id should not be none")
|
|
265
|
+
return None
|
|
266
|
+
|
|
267
|
+
data_store = self.sas_client.get_instance(data_store_id)
|
|
268
|
+
database = self.create_database_alt(data_store)
|
|
269
|
+
self.db_schema_name = data_store["name"]
|
|
270
|
+
db_schema = CreateDatabaseSchemaRequest(
|
|
271
|
+
name=data_store["name"], database=database.fullyQualifiedName
|
|
272
|
+
)
|
|
273
|
+
db_schema_entity = self.metadata.create_or_update(db_schema)
|
|
274
|
+
return db_schema_entity
|
|
275
|
+
|
|
276
|
+
def create_columns_alt(self, table):
|
|
277
|
+
"""
|
|
278
|
+
Create columns by loading the table when they are not already loaded
|
|
279
|
+
"""
|
|
280
|
+
columns_endpoint = ""
|
|
281
|
+
load_endpoint = ""
|
|
282
|
+
for link in table["links"]:
|
|
283
|
+
if link["rel"] == "columns":
|
|
284
|
+
columns_endpoint = link["uri"][1:] + "?limit=1000"
|
|
285
|
+
if link["rel"] == "load":
|
|
286
|
+
load_endpoint = link["uri"][1:]
|
|
287
|
+
if load_endpoint:
|
|
288
|
+
self.sas_client.load_table(load_endpoint)
|
|
289
|
+
columns_resource = self.sas_client.get_resource(columns_endpoint)
|
|
290
|
+
columns = []
|
|
291
|
+
for item in columns_resource["items"]:
|
|
292
|
+
datatype = item["type"]
|
|
293
|
+
if datatype == "num":
|
|
294
|
+
datatype = "numeric"
|
|
295
|
+
parsed_string = ColumnTypeParser._parse_datatype_string(datatype)
|
|
296
|
+
col_name = item["name"]
|
|
297
|
+
parsed_string["name"] = col_name.replace('"', "'")
|
|
298
|
+
parsed_string["ordinalPosition"] = item["index"]
|
|
299
|
+
if datatype.lower() in ["char", "varchar", "binary", "varbinary"]:
|
|
300
|
+
parsed_string["dataLength"] = 0
|
|
301
|
+
col = Column(**parsed_string)
|
|
302
|
+
columns.append(col)
|
|
303
|
+
return columns
|
|
304
|
+
|
|
305
|
+
def get_entities_using_view(self, table_id):
|
|
306
|
+
"""
|
|
307
|
+
Get all the col_entity_instances related to table using views
|
|
308
|
+
"""
|
|
309
|
+
views_query = {
|
|
310
|
+
"query": "match (t:dataSet)-[r:dataSetDataFields]->(c:dataField) return t,r,c",
|
|
311
|
+
"parameters": {"t": {"id": f"{table_id}"}},
|
|
312
|
+
}
|
|
313
|
+
views_data = json.dumps(views_query)
|
|
314
|
+
views = self.sas_client.get_views(views_data)
|
|
315
|
+
if not views.get("entities"): # if the resource is not a table
|
|
316
|
+
return None, None
|
|
317
|
+
|
|
318
|
+
col_entity_instances = views["entities"]
|
|
319
|
+
# find datatables in col_entity_instances
|
|
320
|
+
table_entity_instance = list(
|
|
321
|
+
filter(lambda x: "Table" in x["type"], col_entity_instances)
|
|
322
|
+
)
|
|
323
|
+
if len(table_entity_instance) == 1:
|
|
324
|
+
table_entity_instance = table_entity_instance[0]
|
|
325
|
+
|
|
326
|
+
return col_entity_instances, table_entity_instance
|
|
327
|
+
|
|
328
|
+
def get_table_fqn(self, table_name):
|
|
329
|
+
return fqn.build(
|
|
330
|
+
self.metadata,
|
|
331
|
+
entity_type=Table,
|
|
332
|
+
service_name=self.db_service_name,
|
|
333
|
+
database_name=self.db_name,
|
|
334
|
+
schema_name=self.db_schema_name,
|
|
335
|
+
table_name=table_name,
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
def create_columns_and_profiles(self, entities, table_entity_instance):
|
|
339
|
+
"""
|
|
340
|
+
Create columns and profiles
|
|
341
|
+
"""
|
|
342
|
+
columns = []
|
|
343
|
+
col_profile_list = []
|
|
344
|
+
for entity in entities:
|
|
345
|
+
if entity["id"] == table_entity_instance["id"]:
|
|
346
|
+
continue
|
|
347
|
+
if "Column" not in entity["type"]:
|
|
348
|
+
continue
|
|
349
|
+
col_attributes = entity["attributes"]
|
|
350
|
+
if "casDataType" in col_attributes:
|
|
351
|
+
datatype = col_attributes["casDataType"]
|
|
352
|
+
else:
|
|
353
|
+
datatype = col_attributes["dataType"]
|
|
354
|
+
if datatype == "num":
|
|
355
|
+
datatype = "numeric"
|
|
356
|
+
parsed_string = ColumnTypeParser._parse_datatype_string(datatype)
|
|
357
|
+
col_name = entity["name"]
|
|
358
|
+
parsed_string["name"] = col_name.replace('"', "'")
|
|
359
|
+
parsed_string["ordinalPosition"] = col_attributes["ordinalPosition"]
|
|
360
|
+
# Column profile to be added
|
|
361
|
+
attr_map = {
|
|
362
|
+
"mean": "mean",
|
|
363
|
+
"median": "sum",
|
|
364
|
+
"min": "min",
|
|
365
|
+
"max": "max",
|
|
366
|
+
"standardDeviation": "stddev",
|
|
367
|
+
"missingCount": "nullCount",
|
|
368
|
+
"completenessPercent": "valuesPercentage",
|
|
369
|
+
"uniquenessPercent": "uniqueProportion",
|
|
370
|
+
"cardinalityCount": "distinctCount",
|
|
371
|
+
"skewness": "nonParametricSkew",
|
|
372
|
+
"quantiles25": "firstQuartile",
|
|
373
|
+
"quantiles50": "median",
|
|
374
|
+
"quantiles75": "thirdQuartile",
|
|
375
|
+
"mismatchedCount": "missingCount",
|
|
376
|
+
"charsMinCount": "minLength",
|
|
377
|
+
"charsMaxCount": "maxLength",
|
|
378
|
+
}
|
|
379
|
+
col_profile_dict = {}
|
|
380
|
+
for attr, mapped_attr in attr_map.items():
|
|
381
|
+
if attr in col_attributes:
|
|
382
|
+
if attr == "uniquenessPercent":
|
|
383
|
+
col_profile_dict[mapped_attr] = col_attributes[attr] / 100
|
|
384
|
+
else:
|
|
385
|
+
col_profile_dict[mapped_attr] = col_attributes[attr]
|
|
386
|
+
if "rowCount" in table_entity_instance["attributes"]:
|
|
387
|
+
col_profile_dict["valuesCount"] = table_entity_instance["attributes"][
|
|
388
|
+
"rowCount"
|
|
389
|
+
]
|
|
390
|
+
if "valuesCount" in col_profile_dict:
|
|
391
|
+
if "distinctCount" in col_profile_dict:
|
|
392
|
+
col_profile_dict["distinctProportion"] = (
|
|
393
|
+
col_profile_dict["distinctCount"]
|
|
394
|
+
/ col_profile_dict["valuesCount"]
|
|
395
|
+
)
|
|
396
|
+
col_profile_dict["uniqueCount"] = col_profile_dict["distinctCount"]
|
|
397
|
+
if "nullCount" in col_profile_dict:
|
|
398
|
+
col_profile_dict["nullProportion"] = (
|
|
399
|
+
col_profile_dict["nullCount"] / col_profile_dict["valuesCount"]
|
|
400
|
+
)
|
|
401
|
+
if "missingCount" in col_profile_dict:
|
|
402
|
+
col_profile_dict["missingPercentage"] = (
|
|
403
|
+
col_profile_dict["missingCount"]
|
|
404
|
+
/ col_profile_dict["valuesCount"]
|
|
405
|
+
)
|
|
406
|
+
col_profile_dict["validCount"] = (
|
|
407
|
+
col_profile_dict["valuesCount"]
|
|
408
|
+
- col_profile_dict["missingCount"]
|
|
409
|
+
)
|
|
410
|
+
timestamp = time.time() - 100000
|
|
411
|
+
col_profile_dict["timestamp"] = timestamp
|
|
412
|
+
col_profile_dict["name"] = parsed_string["name"]
|
|
413
|
+
column_profile = ColumnProfile(**col_profile_dict)
|
|
414
|
+
col_profile_list.append(column_profile)
|
|
415
|
+
parsed_string["profile"] = column_profile
|
|
416
|
+
if datatype.lower() in ["char", "varchar", "binary", "varbinary"]:
|
|
417
|
+
if "charsMaxCount" in col_attributes:
|
|
418
|
+
parsed_string["dataLength"] = col_attributes["charsMaxCount"]
|
|
419
|
+
else:
|
|
420
|
+
parsed_string["dataLength"] = 0
|
|
421
|
+
logger.info(f"This is parsed string: {parsed_string}")
|
|
422
|
+
col = Column(**parsed_string)
|
|
423
|
+
columns.append(col)
|
|
424
|
+
return columns, col_profile_list
|
|
425
|
+
|
|
426
|
+
def create_table_entity(self, table) -> Iterable[Either[CreateTableRequest]]:
|
|
427
|
+
# pylint: disable=global-variable-undefined
|
|
428
|
+
"""
|
|
429
|
+
Create database + db service & Create database schema
|
|
430
|
+
"""
|
|
431
|
+
logger.info(f"Ingesting table: {table}")
|
|
432
|
+
global table_entity
|
|
433
|
+
global table_fqn
|
|
434
|
+
|
|
435
|
+
table_entity, table_fqn = None, None
|
|
436
|
+
|
|
437
|
+
try:
|
|
438
|
+
table_url = self.sas_client.get_information_catalog_link(table["id"])
|
|
439
|
+
col_entity_instances, table_entity_instance = self.get_entities_using_view(
|
|
440
|
+
table["id"]
|
|
441
|
+
)
|
|
442
|
+
logger.info(f"table entity: {table_entity_instance}")
|
|
443
|
+
|
|
444
|
+
if not table_entity_instance:
|
|
445
|
+
return
|
|
446
|
+
|
|
447
|
+
table_name = table_entity_instance["name"]
|
|
448
|
+
table_extension = table_entity_instance["attributes"]
|
|
449
|
+
|
|
450
|
+
# create tables in database
|
|
451
|
+
database_schema = self.create_database_schema(table_entity_instance)
|
|
452
|
+
|
|
453
|
+
# find the table entity to see if it already exists
|
|
454
|
+
table_fqn = self.get_table_fqn(table_name)
|
|
455
|
+
table_entity = self.metadata.get_by_name(
|
|
456
|
+
entity=Table, fqn=table_fqn, fields=["extension"]
|
|
457
|
+
)
|
|
458
|
+
|
|
459
|
+
logger.debug(table_entity)
|
|
460
|
+
|
|
461
|
+
# if the table entity already exists, we don't need to create it again
|
|
462
|
+
# only update it when either the sourceUrl or analysisTimeStamp changed
|
|
463
|
+
if not table_entity or (
|
|
464
|
+
table_url != table_entity.sourceUrl.__root__
|
|
465
|
+
or table_entity.extension.__root__.get("analysisTimeStamp")
|
|
466
|
+
!= table_extension.get("analysisTimeStamp")
|
|
467
|
+
):
|
|
468
|
+
# create the columns of the table
|
|
469
|
+
columns, col_profile_list = self.create_columns_and_profiles(
|
|
470
|
+
col_entity_instances, table_entity_instance
|
|
471
|
+
)
|
|
472
|
+
|
|
473
|
+
# set description based on col counts
|
|
474
|
+
if len(columns) == 0:
|
|
475
|
+
table_description = (
|
|
476
|
+
"Table has not been analyzed. "
|
|
477
|
+
f'Head over to <a target="_blank" href="{table_url}">'
|
|
478
|
+
f"SAS Information Catalog</a> to analyze the table."
|
|
479
|
+
)
|
|
480
|
+
try:
|
|
481
|
+
# Create columns alternatively
|
|
482
|
+
table_resource = self.sas_client.get_resource(
|
|
483
|
+
table_entity_instance["resourceId"][1:]
|
|
484
|
+
)
|
|
485
|
+
columns = self.create_columns_alt(table_resource)
|
|
486
|
+
except HTTPError as http_err:
|
|
487
|
+
table_description = f"{str(http_err)} This table does not exist in the file path"
|
|
488
|
+
else:
|
|
489
|
+
table_description = (
|
|
490
|
+
f"Last analyzed: <b>{table_extension.get('analysisTimeStamp')}</b>. "
|
|
491
|
+
f'Visit <a target="_blank" href="{table_url}">SAS Information Catalog</a>'
|
|
492
|
+
f" for more information."
|
|
493
|
+
)
|
|
494
|
+
|
|
495
|
+
# build table extension attr
|
|
496
|
+
for attr in table_extension:
|
|
497
|
+
if isinstance(table_extension[attr], bool):
|
|
498
|
+
table_extension[attr] = str(table_extension[attr])
|
|
499
|
+
|
|
500
|
+
custom_attributes = [
|
|
501
|
+
custom_attribute["name"] for custom_attribute in TABLE_CUSTOM_ATTR
|
|
502
|
+
]
|
|
503
|
+
extension_attributes = {
|
|
504
|
+
attr: value
|
|
505
|
+
for attr, value in table_extension.items()
|
|
506
|
+
if attr in custom_attributes
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
table_request = CreateTableRequest(
|
|
510
|
+
name=table_name,
|
|
511
|
+
sourceUrl=table_url,
|
|
512
|
+
description=table_description,
|
|
513
|
+
columns=columns,
|
|
514
|
+
databaseSchema=database_schema.fullyQualifiedName,
|
|
515
|
+
extension=extension_attributes,
|
|
516
|
+
)
|
|
517
|
+
|
|
518
|
+
yield Either(right=table_request)
|
|
519
|
+
|
|
520
|
+
# find the table entity to see if it already exists
|
|
521
|
+
yield from self.create_lineage_table_source(table_extension, table_name)
|
|
522
|
+
|
|
523
|
+
table_entity = self.metadata.get_by_name(
|
|
524
|
+
entity=Table, fqn=self.get_table_fqn(table_name)
|
|
525
|
+
)
|
|
526
|
+
# update the description
|
|
527
|
+
logger.debug(
|
|
528
|
+
f"Updating description for {table_entity.id.__root__} with {table_description}"
|
|
529
|
+
)
|
|
530
|
+
self.metadata.client.patch(
|
|
531
|
+
path=f"/tables/{table_entity.id.__root__}",
|
|
532
|
+
data=json.dumps(
|
|
533
|
+
[
|
|
534
|
+
{
|
|
535
|
+
"op": "add",
|
|
536
|
+
"path": "/description",
|
|
537
|
+
"value": table_description,
|
|
538
|
+
}
|
|
539
|
+
]
|
|
540
|
+
),
|
|
541
|
+
)
|
|
542
|
+
|
|
543
|
+
# update the custom properties
|
|
544
|
+
logger.debug(
|
|
545
|
+
f"Updating custom properties for {table_entity.id.__root__} with {extension_attributes}"
|
|
546
|
+
)
|
|
547
|
+
self.metadata.client.patch(
|
|
548
|
+
path=f"/tables/{table_entity.id.__root__}",
|
|
549
|
+
data=json.dumps(
|
|
550
|
+
[
|
|
551
|
+
{
|
|
552
|
+
"op": "add",
|
|
553
|
+
"path": "/extension",
|
|
554
|
+
"value": extension_attributes,
|
|
555
|
+
}
|
|
556
|
+
]
|
|
557
|
+
),
|
|
558
|
+
)
|
|
559
|
+
|
|
560
|
+
# quit updating table profile if table doesn't exist
|
|
561
|
+
if (
|
|
562
|
+
table_description
|
|
563
|
+
and "This table does not exist in the file path"
|
|
564
|
+
in table_description
|
|
565
|
+
):
|
|
566
|
+
return
|
|
567
|
+
|
|
568
|
+
# update table profile
|
|
569
|
+
table_profile_dict = {
|
|
570
|
+
"timestamp": time.time() - 100000,
|
|
571
|
+
"createDateTime": table_entity_instance["creationTimeStamp"],
|
|
572
|
+
"rowCount": (
|
|
573
|
+
0
|
|
574
|
+
if "rowCount" not in table_extension
|
|
575
|
+
else table_extension["rowCount"]
|
|
576
|
+
),
|
|
577
|
+
"columnCount": (
|
|
578
|
+
0
|
|
579
|
+
if "columnCount" not in table_extension
|
|
580
|
+
else table_extension["columnCount"]
|
|
581
|
+
),
|
|
582
|
+
"sizeInByte": (
|
|
583
|
+
0
|
|
584
|
+
if "dataSize" not in extension_attributes
|
|
585
|
+
else table_extension["dataSize"]
|
|
586
|
+
),
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
# create Profiles & Data Quality Column
|
|
590
|
+
table_profile_request = CreateTableProfileRequest(
|
|
591
|
+
tableProfile=TableProfile(**table_profile_dict),
|
|
592
|
+
columnProfile=col_profile_list,
|
|
593
|
+
)
|
|
594
|
+
self.metadata.client.put(
|
|
595
|
+
path=f"{self.metadata.get_suffix(Table)}/{table_entity.id.__root__}/tableProfile",
|
|
596
|
+
data=table_profile_request.json(),
|
|
597
|
+
)
|
|
598
|
+
|
|
599
|
+
except Exception as exc:
|
|
600
|
+
logger.error(f"table failed to create: {table}")
|
|
601
|
+
yield Either(
|
|
602
|
+
left=StackTraceError(
|
|
603
|
+
name=table_name,
|
|
604
|
+
error=f"Unexpected exception to create table [{table_name}]: {exc}",
|
|
605
|
+
stack_trace=traceback.format_exc(),
|
|
606
|
+
)
|
|
607
|
+
)
|
|
608
|
+
finally:
|
|
609
|
+
if table_entity:
|
|
610
|
+
self.table_fqns.append(table_fqn)
|
|
611
|
+
|
|
612
|
+
def create_lineage_table_source(self, table_extension, table_name):
|
|
613
|
+
"""
|
|
614
|
+
create lineage between the table and its source
|
|
615
|
+
"""
|
|
616
|
+
if "sourceName" in table_extension and table_extension["sourceName"] != "":
|
|
617
|
+
source_name = table_extension["sourceName"]
|
|
618
|
+
# see if the source table already exists
|
|
619
|
+
source_table_fqn = self.get_table_fqn(source_name)
|
|
620
|
+
logger.debug(f"source_table_fqn for sourceTable is {source_table_fqn}")
|
|
621
|
+
source_table_entity = self.metadata.get_by_name(
|
|
622
|
+
entity=Table, fqn=source_table_fqn
|
|
623
|
+
)
|
|
624
|
+
target_table_entity = self.metadata.get_by_name(
|
|
625
|
+
entity=Table, fqn=self.get_table_fqn(table_name)
|
|
626
|
+
)
|
|
627
|
+
|
|
628
|
+
# process to create lineage if source table doesn't exist
|
|
629
|
+
if not source_table_entity:
|
|
630
|
+
sanitized_source_name = re.sub("[@!#$%^&*]", "", source_name)
|
|
631
|
+
param = f"filter=contains(name, '{sanitized_source_name}')"
|
|
632
|
+
get_instances_with_param = self.sas_client.get_instances_with_param(
|
|
633
|
+
param
|
|
634
|
+
)
|
|
635
|
+
if get_instances_with_param and len(get_instances_with_param) == 1:
|
|
636
|
+
source_table = get_instances_with_param[0]
|
|
637
|
+
yield from self.create_table_entity(source_table)
|
|
638
|
+
|
|
639
|
+
source_table_entity = self.metadata.get_by_name(
|
|
640
|
+
entity=Table, fqn=source_table_fqn
|
|
641
|
+
)
|
|
642
|
+
|
|
643
|
+
if source_table_entity:
|
|
644
|
+
yield from self.create_table_lineage(
|
|
645
|
+
source_table_entity, target_table_entity
|
|
646
|
+
)
|
|
647
|
+
|
|
648
|
+
def add_table_custom_attributes(self):
|
|
649
|
+
"""
|
|
650
|
+
Adding custom attribute from extension_attr.py
|
|
651
|
+
"""
|
|
652
|
+
string_type = self.metadata.client.get(path="/metadata/types/name/string")["id"]
|
|
653
|
+
integer_type = self.metadata.client.get(path="/metadata/types/name/integer")[
|
|
654
|
+
"id"
|
|
655
|
+
]
|
|
656
|
+
for attr in TABLE_CUSTOM_ATTR:
|
|
657
|
+
if attr["propertyType"]["id"] == "STRING_TYPE":
|
|
658
|
+
attr["propertyType"]["id"] = string_type
|
|
659
|
+
else:
|
|
660
|
+
attr["propertyType"]["id"] = integer_type
|
|
661
|
+
table_type = self.metadata.client.get(path="/metadata/types/name/table")
|
|
662
|
+
table_id = table_type["id"]
|
|
663
|
+
for attr in TABLE_CUSTOM_ATTR:
|
|
664
|
+
self.metadata.client.put(
|
|
665
|
+
path=f"/metadata/types/{table_id}", data=json.dumps(attr)
|
|
666
|
+
)
|
|
667
|
+
|
|
668
|
+
def create_table_lineage(self, from_entity, to_entity):
|
|
669
|
+
yield self.create_lineage_request("table", "table", from_entity, to_entity)
|
|
670
|
+
|
|
671
|
+
def create_dashboard_service(self, dashboard_service_name):
|
|
672
|
+
self.dashboard_service_name = dashboard_service_name
|
|
673
|
+
|
|
674
|
+
try:
|
|
675
|
+
dashboard_service_request = CreateDashboardServiceRequest(
|
|
676
|
+
name=dashboard_service_name,
|
|
677
|
+
serviceType=DashboardServiceType.CustomDashboard,
|
|
678
|
+
connection=DashboardConnection(
|
|
679
|
+
config=CustomDashboardConnection(
|
|
680
|
+
type=CustomDashboardType.CustomDashboard,
|
|
681
|
+
sourcePythonClass="metadata.ingestion.source.database.customdatabase.metadata.SASDB",
|
|
682
|
+
)
|
|
683
|
+
),
|
|
684
|
+
)
|
|
685
|
+
yield Either(right=dashboard_service_request)
|
|
686
|
+
except Exception as exc:
|
|
687
|
+
yield Either(
|
|
688
|
+
left=StackTraceError(
|
|
689
|
+
name=dashboard_service_name,
|
|
690
|
+
error=f"Unexpected exception to create dashboard service for [{dashboard_service_name}]: {exc}",
|
|
691
|
+
stack_trace=traceback.format_exc(),
|
|
692
|
+
)
|
|
693
|
+
)
|
|
694
|
+
|
|
695
|
+
def get_report_tables(self, report_id):
|
|
696
|
+
"""
|
|
697
|
+
Get datasets related to the report
|
|
698
|
+
"""
|
|
699
|
+
report_tables = self.sas_client.get_report_relationship(report_id)
|
|
700
|
+
table_instances = []
|
|
701
|
+
self.report_description = []
|
|
702
|
+
# loop through each relatedResourceUri from relationships
|
|
703
|
+
for table in report_tables:
|
|
704
|
+
table_uri = table["relatedResourceUri"][1:]
|
|
705
|
+
try:
|
|
706
|
+
# load the table if it can be found
|
|
707
|
+
table_resource = self.sas_client.get_resource(table_uri)
|
|
708
|
+
table_data_resource = table_resource["tableReference"]["tableUri"]
|
|
709
|
+
param = f"filter=eq(resourceId,'{table_data_resource}')"
|
|
710
|
+
if "state" in table_resource and table_resource["state"] == "unloaded":
|
|
711
|
+
self.sas_client.load_table(table_uri + "/state?value=loaded")
|
|
712
|
+
|
|
713
|
+
except HTTPError as exc:
|
|
714
|
+
# append http error to table description if it can't be found
|
|
715
|
+
logger.error(f"table_uri: {table_uri}")
|
|
716
|
+
self.report_description.append(str(exc))
|
|
717
|
+
name_index = table_uri.rindex("/")
|
|
718
|
+
table_name = table_uri[name_index + 1 :]
|
|
719
|
+
param = f"filter=eq(name,'{table_name}')"
|
|
720
|
+
|
|
721
|
+
get_instances_with_param = self.sas_client.get_instances_with_param(param)
|
|
722
|
+
if get_instances_with_param and len(get_instances_with_param) == 1:
|
|
723
|
+
table_instance = get_instances_with_param[0]
|
|
724
|
+
table_instances.append(table_instance)
|
|
725
|
+
return table_instances
|
|
726
|
+
|
|
727
|
+
def create_lineage_request(self, from_type, in_type, from_entity, to_entity):
|
|
728
|
+
return Either(
|
|
729
|
+
right=AddLineageRequest(
|
|
730
|
+
edge=EntitiesEdge(
|
|
731
|
+
fromEntity=EntityReference(
|
|
732
|
+
id=from_entity.id.__root__, type=from_type
|
|
733
|
+
),
|
|
734
|
+
toEntity=EntityReference(id=to_entity.id.__root__, type=in_type),
|
|
735
|
+
)
|
|
736
|
+
)
|
|
737
|
+
)
|
|
738
|
+
|
|
739
|
+
def create_report_entity(self, report):
|
|
740
|
+
"""
|
|
741
|
+
Create report entity and its corresponding lineage to the datasets
|
|
742
|
+
"""
|
|
743
|
+
report_id = report["id"]
|
|
744
|
+
report_name = report["name"]
|
|
745
|
+
try:
|
|
746
|
+
report_resource = report["resourceId"]
|
|
747
|
+
report_url = self.sas_client.get_report_link("report", report_resource)
|
|
748
|
+
self.report_description = (
|
|
749
|
+
str(self.report_description) if self.report_description else None
|
|
750
|
+
)
|
|
751
|
+
report_request = CreateDashboardRequest(
|
|
752
|
+
name=report_id,
|
|
753
|
+
displayName=report_name,
|
|
754
|
+
sourceUrl=report_url,
|
|
755
|
+
charts=self.chart_names,
|
|
756
|
+
service=self.dashboard_service_name,
|
|
757
|
+
description=self.report_description,
|
|
758
|
+
)
|
|
759
|
+
yield Either(right=report_request)
|
|
760
|
+
|
|
761
|
+
dashboard_fqn = fqn.build(
|
|
762
|
+
self.metadata,
|
|
763
|
+
entity_type=Dashboard,
|
|
764
|
+
service_name=self.dashboard_service_name,
|
|
765
|
+
dashboard_name=report_id,
|
|
766
|
+
)
|
|
767
|
+
|
|
768
|
+
dashboard_entity = self.metadata.get_by_name(
|
|
769
|
+
entity=Dashboard, fqn=dashboard_fqn
|
|
770
|
+
)
|
|
771
|
+
table_entities = []
|
|
772
|
+
for table in self.table_fqns:
|
|
773
|
+
entity_instance = self.metadata.get_by_name(entity=Table, fqn=table)
|
|
774
|
+
table_entities.append(entity_instance)
|
|
775
|
+
for entity in table_entities:
|
|
776
|
+
yield self.create_lineage_request(
|
|
777
|
+
"table", "dashboard", entity, dashboard_entity
|
|
778
|
+
)
|
|
779
|
+
except Exception as exc:
|
|
780
|
+
logger.error(f"report failed to create: {report}")
|
|
781
|
+
yield Either(
|
|
782
|
+
left=StackTraceError(
|
|
783
|
+
name=report_name,
|
|
784
|
+
error=f"Unexpected exception to create report [{report['id']}]: {exc}",
|
|
785
|
+
stack_trace=traceback.format_exc(),
|
|
786
|
+
)
|
|
787
|
+
)
|
|
788
|
+
|
|
789
|
+
def create_data_flow_entity(self, data_flow, input_fqns, output_fqns):
|
|
790
|
+
"""
|
|
791
|
+
Create data flow and its corresponding lineage with the input & output table
|
|
792
|
+
"""
|
|
793
|
+
data_flow_id = data_flow["id"]
|
|
794
|
+
data_flow_resource = data_flow["resourceId"]
|
|
795
|
+
|
|
796
|
+
try:
|
|
797
|
+
data_flow_url = self.sas_client.get_report_link(
|
|
798
|
+
"dataFlow", data_flow_resource
|
|
799
|
+
)
|
|
800
|
+
data_flow_request = CreateDashboardRequest(
|
|
801
|
+
name=data_flow_id,
|
|
802
|
+
displayName=data_flow["name"],
|
|
803
|
+
service=self.dashboard_service_name,
|
|
804
|
+
sourceUrl=data_flow_url,
|
|
805
|
+
)
|
|
806
|
+
yield Either(right=data_flow_request)
|
|
807
|
+
|
|
808
|
+
dashboard_fqn = fqn.build(
|
|
809
|
+
self.metadata,
|
|
810
|
+
entity_type=Dashboard,
|
|
811
|
+
service_name=self.dashboard_service_name,
|
|
812
|
+
dashboard_name=data_flow_id,
|
|
813
|
+
)
|
|
814
|
+
|
|
815
|
+
dashboard_entity = self.metadata.get_by_name(
|
|
816
|
+
entity=Dashboard, fqn=dashboard_fqn
|
|
817
|
+
)
|
|
818
|
+
|
|
819
|
+
input_entities = [
|
|
820
|
+
self.metadata.get_by_name(entity=Table, fqn=input_entity)
|
|
821
|
+
for input_entity in input_fqns
|
|
822
|
+
]
|
|
823
|
+
output_entities = [
|
|
824
|
+
self.metadata.get_by_name(entity=Table, fqn=output_entity)
|
|
825
|
+
for output_entity in output_fqns
|
|
826
|
+
]
|
|
827
|
+
|
|
828
|
+
for entity in input_entities:
|
|
829
|
+
yield self.create_lineage_request(
|
|
830
|
+
"table", "dashboard", entity, dashboard_entity
|
|
831
|
+
)
|
|
832
|
+
for entity in output_entities:
|
|
833
|
+
yield self.create_lineage_request(
|
|
834
|
+
"dashboard", "table", dashboard_entity, entity
|
|
835
|
+
)
|
|
836
|
+
except Exception as exc:
|
|
837
|
+
logger.error(f"dataflow failed to create: {data_flow}")
|
|
838
|
+
yield Either(
|
|
839
|
+
left=StackTraceError(
|
|
840
|
+
name=data_flow_id,
|
|
841
|
+
error=f"Unexpected exception to create data flow [{data_flow_id}]: {exc}",
|
|
842
|
+
stack_trace=traceback.format_exc(),
|
|
843
|
+
)
|
|
844
|
+
)
|
|
845
|
+
|
|
846
|
+
def get_database_names(self) -> Iterable[str]:
|
|
847
|
+
for database in self.databases:
|
|
848
|
+
yield database
|
|
849
|
+
|
|
850
|
+
def yield_database(
|
|
851
|
+
self, database_name: str
|
|
852
|
+
) -> Iterable[Either[CreateDatabaseRequest]]:
|
|
853
|
+
yield Either(
|
|
854
|
+
right=CreateDatabaseRequest(
|
|
855
|
+
name=database_name,
|
|
856
|
+
service=self.context.database_service,
|
|
857
|
+
)
|
|
858
|
+
)
|
|
859
|
+
|
|
860
|
+
def get_database_schema_names(self) -> Iterable[Tuple[str, str]]:
|
|
861
|
+
for database, database_schemas in self.database_schemas.items():
|
|
862
|
+
for database_schema in database_schemas:
|
|
863
|
+
yield database, database_schema
|
|
864
|
+
|
|
865
|
+
def yield_database_schema(
|
|
866
|
+
self, schema_name: Tuple[str, str]
|
|
867
|
+
) -> Iterable[Either[CreateDatabaseSchemaRequest]]:
|
|
868
|
+
yield Either(
|
|
869
|
+
right=CreateDatabaseSchemaRequest(
|
|
870
|
+
name=schema_name[1],
|
|
871
|
+
database=fqn.build(
|
|
872
|
+
metadata=self.metadata,
|
|
873
|
+
entity_type=Database,
|
|
874
|
+
service_name=self.context.database_service,
|
|
875
|
+
database_name=schema_name[0],
|
|
876
|
+
),
|
|
877
|
+
)
|
|
878
|
+
)
|
|
879
|
+
|
|
880
|
+
def yield_tag(
|
|
881
|
+
self, schema_name: str
|
|
882
|
+
) -> Iterable[Either[OMetaTagAndClassification]]:
|
|
883
|
+
"""No tags to send"""
|
|
884
|
+
|
|
885
|
+
def yield_view_lineage(self) -> Iterable[Either[AddLineageRequest]]:
|
|
886
|
+
yield from []
|
|
887
|
+
|
|
888
|
+
def get_tables_name_and_type(self) -> Optional[Iterable[Tuple[str, list]]]:
|
|
889
|
+
"""Not implemented"""
|
|
890
|
+
|
|
891
|
+
def yield_table(
|
|
892
|
+
self, table_name_and_type: Tuple[str, list]
|
|
893
|
+
) -> Iterable[Either[Entity]]:
|
|
894
|
+
"""Not implemented"""
|
|
895
|
+
|
|
896
|
+
def get_stored_procedures(self) -> Iterable[Any]:
|
|
897
|
+
"""Not implemented"""
|
|
898
|
+
|
|
899
|
+
def yield_stored_procedure(
|
|
900
|
+
self, stored_procedure: Any
|
|
901
|
+
) -> Iterable[Either[CreateStoredProcedureRequest]]:
|
|
902
|
+
"""Not implemented"""
|
|
903
|
+
|
|
904
|
+
def yield_procedure_lineage_and_queries(
|
|
905
|
+
self,
|
|
906
|
+
) -> Iterable[Either[Union[AddLineageRequest, CreateQueryRequest]]]:
|
|
907
|
+
yield from []
|
|
908
|
+
|
|
909
|
+
def close(self) -> None:
|
|
910
|
+
pass
|
|
911
|
+
|
|
912
|
+
def test_connection(self) -> None:
|
|
913
|
+
test_connection_fn = get_test_connection_fn(self.service_connection)
|
|
914
|
+
test_connection_fn(self.metadata, self.connection_obj, self.service_connection)
|