goe-framework 1.0.6__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.
- goe/__init__.py +17 -0
- goe/conductor/__init__.py +0 -0
- goe/conductor/hybrid_view_service.py +334 -0
- goe/config/__init__.py +0 -0
- goe/config/config_file.py +53 -0
- goe/config/config_validation_functions.py +663 -0
- goe/config/option_descriptions.py +38 -0
- goe/config/orchestration_config.py +996 -0
- goe/config/orchestration_defaults.py +999 -0
- goe/connect/__init__.py +0 -0
- goe/connect/connect.py +555 -0
- goe/connect/connect_backend.py +481 -0
- goe/connect/connect_constants.py +23 -0
- goe/connect/connect_frontend.py +265 -0
- goe/connect/connect_functions.py +112 -0
- goe/connect/connect_transport.py +336 -0
- goe/data_governance/__init__.py +0 -0
- goe/data_governance/cloudera_navigator.py +845 -0
- goe/data_governance/hadoop_data_governance.py +616 -0
- goe/data_governance/hadoop_data_governance_constants.py +90 -0
- goe/data_governance/hadoop_data_governance_interface.py +209 -0
- goe/exceptions.py +25 -0
- goe/filesystem/__init__.py +0 -0
- goe/filesystem/cli_hdfs.py +539 -0
- goe/filesystem/goe_azure.py +483 -0
- goe/filesystem/goe_dfs.py +424 -0
- goe/filesystem/goe_dfs_factory.py +110 -0
- goe/filesystem/goe_gcs.py +352 -0
- goe/filesystem/goe_s3.py +363 -0
- goe/filesystem/web_hdfs.py +507 -0
- goe/goe.py +3526 -0
- goe/listener/__init__.py +0 -0
- goe/listener/__main__.py +36 -0
- goe/listener/api/__init__.py +0 -0
- goe/listener/api/routes/__init__.py +0 -0
- goe/listener/api/routes/docs.py +68 -0
- goe/listener/api/routes/orchestration.py +185 -0
- goe/listener/api/routes/system.py +186 -0
- goe/listener/asgi.py +120 -0
- goe/listener/config/__init__.py +10 -0
- goe/listener/config/application.py +113 -0
- goe/listener/config/gunicorn.conf.py +284 -0
- goe/listener/config/logging.py +81 -0
- goe/listener/config/router.py +44 -0
- goe/listener/core/__init__.py +0 -0
- goe/listener/core/enum.py +24 -0
- goe/listener/core/events.py +44 -0
- goe/listener/core/middleware/__init__.py +6 -0
- goe/listener/core/middleware/compression.py +297 -0
- goe/listener/core/middleware/cors.py +38 -0
- goe/listener/core/middleware/secure_headers.py +37 -0
- goe/listener/core/security.py +46 -0
- goe/listener/core/worker.py +149 -0
- goe/listener/exceptions/__init__.py +38 -0
- goe/listener/exceptions/base.py +279 -0
- goe/listener/exceptions/errors.py +99 -0
- goe/listener/heartbeat.py +47 -0
- goe/listener/prestart.py +85 -0
- goe/listener/schemas/__init__.py +58 -0
- goe/listener/schemas/base.py +102 -0
- goe/listener/schemas/error.py +133 -0
- goe/listener/schemas/generics.py +40 -0
- goe/listener/schemas/orchestration.py +896 -0
- goe/listener/schemas/system.py +191 -0
- goe/listener/services/__init__.py +8 -0
- goe/listener/services/heartbeat.py +115 -0
- goe/listener/services/hybrid_view.py +356 -0
- goe/listener/services/orchestrate.py +24 -0
- goe/listener/services/periodic_tasks.py +196 -0
- goe/listener/services/system.py +126 -0
- goe/listener/utils/__init__.py +10 -0
- goe/listener/utils/cache.py +444 -0
- goe/listener/utils/group_by.py +26 -0
- goe/listener/utils/orchestrate.py +52 -0
- goe/listener/utils/ping.py +47 -0
- goe/listener/utils/system.py +83 -0
- goe/listener/worker.py +67 -0
- goe/listener/wsgi.py +130 -0
- goe/offload/__init__.py +0 -0
- goe/offload/backend_api.py +2081 -0
- goe/offload/backend_table.py +2645 -0
- goe/offload/bigquery/__init__.py +0 -0
- goe/offload/bigquery/bigquery_backend_api.py +2579 -0
- goe/offload/bigquery/bigquery_backend_table.py +664 -0
- goe/offload/bigquery/bigquery_column.py +167 -0
- goe/offload/bigquery/bigquery_literal.py +137 -0
- goe/offload/bigquery/bigquery_predicate.py +68 -0
- goe/offload/column_metadata.py +672 -0
- goe/offload/factory/__init__.py +0 -0
- goe/offload/factory/backend_api_factory.py +130 -0
- goe/offload/factory/backend_table_factory.py +162 -0
- goe/offload/factory/frontend_api_factory.py +96 -0
- goe/offload/factory/offload_source_table_factory.py +92 -0
- goe/offload/factory/offload_transport_factory.py +237 -0
- goe/offload/factory/offload_transport_rdbms_api_factory.py +64 -0
- goe/offload/factory/query_import_factory.py +45 -0
- goe/offload/factory/staging_file_factory.py +92 -0
- goe/offload/format_literal.py +70 -0
- goe/offload/frontend_api.py +882 -0
- goe/offload/hadoop/__init__.py +0 -0
- goe/offload/hadoop/hadoop_backend_api.py +1961 -0
- goe/offload/hadoop/hadoop_backend_table.py +898 -0
- goe/offload/hadoop/hadoop_column.py +151 -0
- goe/offload/hadoop/hadoop_predicate.py +82 -0
- goe/offload/hadoop/hive_backend_api.py +755 -0
- goe/offload/hadoop/hive_backend_table.py +257 -0
- goe/offload/hadoop/hive_literal.py +91 -0
- goe/offload/hadoop/impala_backend_api.py +1215 -0
- goe/offload/hadoop/impala_backend_table.py +273 -0
- goe/offload/hadoop/impala_literal.py +68 -0
- goe/offload/hadoop/sqoop_offload_transport.py +612 -0
- goe/offload/microsoft/__init__.py +0 -0
- goe/offload/microsoft/mssql_column.py +228 -0
- goe/offload/microsoft/mssql_frontend_api.py +650 -0
- goe/offload/microsoft/mssql_offload_source_table.py +735 -0
- goe/offload/microsoft/mssql_offload_transport_rdbms_api.py +204 -0
- goe/offload/microsoft/synapse_backend_api.py +2890 -0
- goe/offload/microsoft/synapse_backend_table.py +663 -0
- goe/offload/microsoft/synapse_column.py +220 -0
- goe/offload/microsoft/synapse_constants.py +29 -0
- goe/offload/microsoft/synapse_literal.py +156 -0
- goe/offload/microsoft/synapse_predicate.py +71 -0
- goe/offload/offload.py +706 -0
- goe/offload/offload_constants.py +605 -0
- goe/offload/offload_functions.py +588 -0
- goe/offload/offload_messages.py +708 -0
- goe/offload/offload_metadata_functions.py +462 -0
- goe/offload/offload_source_data.py +3257 -0
- goe/offload/offload_source_table.py +1295 -0
- goe/offload/offload_status_report.py +4038 -0
- goe/offload/offload_transport.py +2873 -0
- goe/offload/offload_transport_functions.py +466 -0
- goe/offload/offload_transport_rdbms_api.py +289 -0
- goe/offload/offload_validation.py +1052 -0
- goe/offload/offload_xform_functions.py +100 -0
- goe/offload/operation/__init__.py +0 -0
- goe/offload/operation/data_type_controls.py +365 -0
- goe/offload/operation/ddl_file.py +125 -0
- goe/offload/operation/not_null_columns.py +107 -0
- goe/offload/operation/partition_controls.py +521 -0
- goe/offload/operation/sort_columns.py +152 -0
- goe/offload/operation/stats_controls.py +425 -0
- goe/offload/operation/table_structure_checks.py +181 -0
- goe/offload/operation/transport.py +167 -0
- goe/offload/option_validation.py +217 -0
- goe/offload/oracle/__init__.py +0 -0
- goe/offload/oracle/oracle_column.py +326 -0
- goe/offload/oracle/oracle_frontend_api.py +1200 -0
- goe/offload/oracle/oracle_literal.py +129 -0
- goe/offload/oracle/oracle_offload_source_table.py +1765 -0
- goe/offload/oracle/oracle_offload_transport_rdbms_api.py +1106 -0
- goe/offload/oracle/oracle_predicate.py +129 -0
- goe/offload/predicate_offload.py +742 -0
- goe/offload/query_import_interface.py +92 -0
- goe/offload/snowflake/__init__.py +0 -0
- goe/offload/snowflake/snowflake_backend_api.py +2326 -0
- goe/offload/snowflake/snowflake_backend_table.py +747 -0
- goe/offload/snowflake/snowflake_column.py +161 -0
- goe/offload/snowflake/snowflake_literal.py +124 -0
- goe/offload/snowflake/snowflake_predicate.py +67 -0
- goe/offload/spark/__init__.py +0 -0
- goe/offload/spark/dataproc_offload_transport.py +615 -0
- goe/offload/spark/livy_offload_transport.py +551 -0
- goe/offload/spark/offload_transport_livy_requests.py +113 -0
- goe/offload/spark/pyspark_literal.py +69 -0
- goe/offload/spark/spark_thrift_backend_api.py +257 -0
- goe/offload/staging/__init__.py +0 -0
- goe/offload/staging/avro/__init__.py +0 -0
- goe/offload/staging/avro/avro_column.py +108 -0
- goe/offload/staging/avro/avro_staging_file.py +416 -0
- goe/offload/staging/parquet/__init__.py +0 -0
- goe/offload/staging/parquet/parquet_column.py +113 -0
- goe/offload/staging/parquet/parquet_staging_file.py +311 -0
- goe/offload/staging/staging_file.py +155 -0
- goe/offload/synthetic_partition_literal.py +249 -0
- goe/offload/teradata/__init__.py +0 -0
- goe/offload/teradata/teradata_column.py +309 -0
- goe/offload/teradata/teradata_frontend_api.py +908 -0
- goe/offload/teradata/teradata_literal.py +162 -0
- goe/offload/teradata/teradata_offload_source_table.py +1192 -0
- goe/offload/teradata/teradata_offload_transport_rdbms_api.py +620 -0
- goe/offload/teradata/teradata_partition_expression.py +205 -0
- goe/offload/teradata/teradata_predicate.py +86 -0
- goe/orchestration/__init__.py +0 -0
- goe/orchestration/cli_entry_points.py +79 -0
- goe/orchestration/command_steps.py +126 -0
- goe/orchestration/execution_id.py +101 -0
- goe/orchestration/orchestration_constants.py +56 -0
- goe/orchestration/orchestration_lock.py +164 -0
- goe/orchestration/orchestration_runner.py +539 -0
- goe/persistence/__init__.py +0 -0
- goe/persistence/factory/__init__.py +0 -0
- goe/persistence/factory/orchestration_repo_client_factory.py +48 -0
- goe/persistence/oracle/__init__.py +0 -0
- goe/persistence/oracle/oracle_orchestration_repo_client.py +1093 -0
- goe/persistence/orchestration_metadata.py +449 -0
- goe/persistence/orchestration_repo_client.py +436 -0
- goe/persistence/teradata/__init__.py +0 -0
- goe/persistence/teradata/teradata_orchestration_repo_client.py +358 -0
- goe/schema_sync/__init__.py +0 -0
- goe/schema_sync/schema_sync.py +170 -0
- goe/schema_sync/schema_sync_analyzer.py +663 -0
- goe/schema_sync/schema_sync_command_file.py +94 -0
- goe/schema_sync/schema_sync_constants.py +38 -0
- goe/schema_sync/schema_sync_processor.py +109 -0
- goe/schema_sync/schema_sync_step.py +91 -0
- goe/schema_sync/steps/__init__.py +0 -0
- goe/schema_sync/steps/add_backend_column.py +107 -0
- goe/schema_sync/steps/add_oracle_column.py +101 -0
- goe/schema_sync/steps/step_builder.py +30 -0
- goe/scripts/__init__.py +0 -0
- goe/scripts/agg_validate.py +288 -0
- goe/util/__init__.py +0 -0
- goe/util/avro_encoder.py +258 -0
- goe/util/better_impyla.py +1748 -0
- goe/util/exception_trigger.py +52 -0
- goe/util/goe_log.py +152 -0
- goe/util/goe_log_fh.py +67 -0
- goe/util/goe_version.py +18 -0
- goe/util/hive_ddl_transform.py +396 -0
- goe/util/hive_table_stats.py +1590 -0
- goe/util/hs2_connection.py +310 -0
- goe/util/json_tools.py +60 -0
- goe/util/local_cache.py +312 -0
- goe/util/misc_functions.py +775 -0
- goe/util/ora_query.py +417 -0
- goe/util/parallel_exec.py +222 -0
- goe/util/parquet_encoder.py +206 -0
- goe/util/password_tools.py +261 -0
- goe/util/polling_thread.py +97 -0
- goe/util/redis_tools.py +443 -0
- goe/util/retry_logic.py +165 -0
- goe/util/simple_timer.py +49 -0
- goe_framework-1.0.6.dist-info/AUTHORS +10 -0
- goe_framework-1.0.6.dist-info/LICENSE +201 -0
- goe_framework-1.0.6.dist-info/METADATA +210 -0
- goe_framework-1.0.6.dist-info/RECORD +239 -0
- goe_framework-1.0.6.dist-info/WHEEL +5 -0
- goe_framework-1.0.6.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,663 @@
|
|
|
1
|
+
#! /usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
# Copyright 2016 The GOE Authors. All rights reserved.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
""" config_validation_functions: Library of functions used in goe.py and OrchestrationConfig
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import json
|
|
21
|
+
import random
|
|
22
|
+
import re
|
|
23
|
+
|
|
24
|
+
from goe.config import orchestration_defaults
|
|
25
|
+
from goe.data_governance.hadoop_data_governance_constants import (
|
|
26
|
+
SUPPORTED_DATA_GOVERNANCE_BACKENDS,
|
|
27
|
+
)
|
|
28
|
+
from goe.data_governance.hadoop_data_governance import (
|
|
29
|
+
is_valid_data_governance_tag,
|
|
30
|
+
is_valid_data_governance_auto_property,
|
|
31
|
+
)
|
|
32
|
+
from goe.filesystem.goe_dfs import (
|
|
33
|
+
AZURE_OFFLOAD_FS_SCHEMES,
|
|
34
|
+
OFFLOAD_FS_SCHEME_MAPRFS,
|
|
35
|
+
VALID_OFFLOAD_FS_SCHEMES,
|
|
36
|
+
OFFLOAD_FS_SCHEMES_REQUIRING_CONTAINER,
|
|
37
|
+
)
|
|
38
|
+
from goe.offload.microsoft.synapse_constants import (
|
|
39
|
+
SYNAPSE_AUTH_MECHANISM_AD_SERVICE_PRINCIPAL,
|
|
40
|
+
SYNAPSE_VALID_AUTH_MECHANISMS,
|
|
41
|
+
SYNAPSE_USER_PASS_AUTH_MECHANISMS,
|
|
42
|
+
)
|
|
43
|
+
from goe.offload.offload_constants import (
|
|
44
|
+
BACKEND_DISTRO_GCP,
|
|
45
|
+
BACKEND_DISTRO_MAPR,
|
|
46
|
+
BACKEND_DISTRO_SNOWFLAKE,
|
|
47
|
+
BACKEND_DISTRO_MSAZURE,
|
|
48
|
+
DBTYPE_HIVE,
|
|
49
|
+
DBTYPE_IMPALA,
|
|
50
|
+
DBTYPE_MSSQL,
|
|
51
|
+
DBTYPE_ORACLE,
|
|
52
|
+
DBTYPE_TERADATA,
|
|
53
|
+
HADOOP_BASED_BACKEND_DISTRIBUTIONS,
|
|
54
|
+
)
|
|
55
|
+
from goe.offload.offload_transport import (
|
|
56
|
+
derive_rest_api_verify_value_from_url,
|
|
57
|
+
SPARK_SUBMIT_SPARK_YARN_MASTER,
|
|
58
|
+
VALID_OFFLOAD_TRANSPORTS,
|
|
59
|
+
VALID_SPARK_SUBMIT_EXECUTABLES,
|
|
60
|
+
)
|
|
61
|
+
from goe.util.goe_log_fh import is_valid_path_for_logs
|
|
62
|
+
from goe.util.misc_functions import human_size_to_bytes
|
|
63
|
+
from goe.util.password_tools import PasswordTools
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class OrchestrationConfigException(Exception):
|
|
67
|
+
pass
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
###########################################################################
|
|
71
|
+
# GLOBAL FUNCTIONS
|
|
72
|
+
###########################################################################
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def verify_json_option(option_name, option_value):
|
|
76
|
+
if option_value:
|
|
77
|
+
try:
|
|
78
|
+
properties = json.loads(option_value)
|
|
79
|
+
|
|
80
|
+
invalid_props = [
|
|
81
|
+
k for k, v in properties.items() if type(v) not in (str, int, float)
|
|
82
|
+
]
|
|
83
|
+
if invalid_props:
|
|
84
|
+
prop_details = "\n".join(
|
|
85
|
+
f"Invalid property value for key/value pair: {k}: {properties[k]}"
|
|
86
|
+
for k in invalid_props
|
|
87
|
+
)
|
|
88
|
+
raise OrchestrationConfigException(
|
|
89
|
+
"Invalid property value in {} for keys: {}\n{}".format(
|
|
90
|
+
option_name, str(invalid_props), prop_details
|
|
91
|
+
)
|
|
92
|
+
)
|
|
93
|
+
except ValueError as ve:
|
|
94
|
+
raise OrchestrationConfigException(
|
|
95
|
+
"Invalid JSON value for %s: %s" % (option_name, str(ve))
|
|
96
|
+
) from ve
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
###########################################################################
|
|
100
|
+
# NORMALISATION FUNCTIONS
|
|
101
|
+
# For the time being these are a lift and shift from goe.py while we
|
|
102
|
+
# migrate to OrchestrationConfig.
|
|
103
|
+
###########################################################################
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def normalise_backend_options(options):
|
|
107
|
+
normalise_bigquery_options(options)
|
|
108
|
+
normalise_hadoop_options(options)
|
|
109
|
+
normalise_snowflake_options(options)
|
|
110
|
+
normalise_synapse_options(options)
|
|
111
|
+
|
|
112
|
+
if options.backend_identifier_case:
|
|
113
|
+
options.backend_identifier_case = options.backend_identifier_case.upper()
|
|
114
|
+
else:
|
|
115
|
+
options.backend_identifier_case = (
|
|
116
|
+
orchestration_defaults.backend_identifier_case_default()
|
|
117
|
+
)
|
|
118
|
+
if options.backend_identifier_case not in ["UPPER", "LOWER", "NO_MODIFY"]:
|
|
119
|
+
raise OrchestrationConfigException(
|
|
120
|
+
"Invalid value for BACKEND_IDENTIFIER_CASE, valid values: UPPER|LOWER|NO_MODIFY"
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def normalise_db_prefix_and_paths(options, frontend_api=None):
|
|
125
|
+
if options.db_name_prefix is None:
|
|
126
|
+
assert frontend_api
|
|
127
|
+
options.db_name_prefix = frontend_api.get_db_unique_name()
|
|
128
|
+
|
|
129
|
+
if options.db_name_prefix and options.db_name_prefix != "":
|
|
130
|
+
options.db_name_pattern = (
|
|
131
|
+
options.db_name_prefix.lower() + "_" + options.db_name_pattern
|
|
132
|
+
)
|
|
133
|
+
options.load_db_name_pattern = (
|
|
134
|
+
options.db_name_prefix.lower() + "_" + options.load_db_name_pattern
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
if not is_valid_path_for_logs(options.log_path):
|
|
138
|
+
raise OrchestrationConfigException(
|
|
139
|
+
f"Invalid value for OFFLOAD_LOGDIR: {options.log_path}"
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def normalise_bigquery_options(options, exc_cls=OrchestrationConfigException):
|
|
144
|
+
if options.backend_distribution != BACKEND_DISTRO_GCP:
|
|
145
|
+
return
|
|
146
|
+
if options.google_dataproc_batches_version:
|
|
147
|
+
if not re.match(
|
|
148
|
+
r"^[1-9]\.[0-9](\.[0-9])?$", options.google_dataproc_batches_version
|
|
149
|
+
):
|
|
150
|
+
raise exc_cls(
|
|
151
|
+
f"Invalid value for GOOGLE_DATAPROC_BATCHES_VERSION: {options.google_dataproc_batches_version}"
|
|
152
|
+
)
|
|
153
|
+
if options.google_dataproc_batches_ttl:
|
|
154
|
+
if not re.match(r"^[1-9][0-9]*[mhd]$", options.google_dataproc_batches_ttl):
|
|
155
|
+
raise exc_cls(
|
|
156
|
+
f"Invalid value for GOOGLE_DATAPROC_BATCHES_TTL: {options.google_dataproc_batches_ttl}"
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def normalise_hadoop_options(options, exc_cls=OrchestrationConfigException):
|
|
161
|
+
if options.backend_distribution not in HADOOP_BASED_BACKEND_DISTRIBUTIONS:
|
|
162
|
+
return
|
|
163
|
+
|
|
164
|
+
if not options.hadoop_host:
|
|
165
|
+
raise exc_cls("HIVE_SERVER_HOST is mandatory")
|
|
166
|
+
|
|
167
|
+
if options.target == DBTYPE_HIVE:
|
|
168
|
+
if not options.hiveserver2_auth_mechanism:
|
|
169
|
+
options.hiveserver2_auth_mechanism = "PLAIN"
|
|
170
|
+
elif options.target == DBTYPE_IMPALA:
|
|
171
|
+
if not options.hiveserver2_auth_mechanism:
|
|
172
|
+
options.hiveserver2_auth_mechanism = "NOSASL"
|
|
173
|
+
|
|
174
|
+
# Select hadoop_host from (potentially) comma-separated list
|
|
175
|
+
options.hadoop_host = random.choice(options.hadoop_host.split(","))
|
|
176
|
+
options.hdfs_host = options.hdfs_host or options.hadoop_host
|
|
177
|
+
|
|
178
|
+
normalise_webhdfs(options)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def normalise_backend_session_parameters(opts):
|
|
182
|
+
if not opts.backend_session_parameters:
|
|
183
|
+
opts.backend_session_parameters = {}
|
|
184
|
+
elif isinstance(opts.backend_session_parameters, str):
|
|
185
|
+
verify_json_option(
|
|
186
|
+
"OFFLOAD_BACKEND_SESSION_PARAMETERS", opts.backend_session_parameters
|
|
187
|
+
)
|
|
188
|
+
opts.backend_session_parameters = json.loads(opts.backend_session_parameters)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def normalise_data_governance_config(options):
|
|
192
|
+
if options.data_governance_api_url:
|
|
193
|
+
if not options.data_governance_backend:
|
|
194
|
+
raise OrchestrationConfigException(
|
|
195
|
+
"DATA_GOVERNANCE_BACKEND is required when connecting to a Data Governance API"
|
|
196
|
+
)
|
|
197
|
+
if options.data_governance_backend not in SUPPORTED_DATA_GOVERNANCE_BACKENDS:
|
|
198
|
+
raise OrchestrationConfigException(
|
|
199
|
+
"Invalid DATA_GOVERNANCE_BACKEND %s. Valid values are: %s"
|
|
200
|
+
% (options.data_governance_backend, SUPPORTED_DATA_GOVERNANCE_BACKENDS)
|
|
201
|
+
)
|
|
202
|
+
if (
|
|
203
|
+
options.data_governance_backend == "navigator"
|
|
204
|
+
and not options.cloudera_navigator_hive_source_id
|
|
205
|
+
):
|
|
206
|
+
raise OrchestrationConfigException(
|
|
207
|
+
"--cloudera-navigator-hive-source-id is required for Cloudera Navigator integration"
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
tag_list = (
|
|
211
|
+
options.data_governance_auto_tags_csv.split(",")
|
|
212
|
+
if options.data_governance_auto_tags_csv
|
|
213
|
+
else []
|
|
214
|
+
)
|
|
215
|
+
invalid_auto_tags = [_ for _ in tag_list if not is_valid_data_governance_tag(_)]
|
|
216
|
+
if invalid_auto_tags:
|
|
217
|
+
# Using env var name for exception because the command line option is hidden
|
|
218
|
+
raise OrchestrationConfigException(
|
|
219
|
+
"Invalid values for DATA_GOVERNANCE_AUTO_TAGS: %s" % invalid_auto_tags
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
auto_properties = (
|
|
223
|
+
options.data_governance_auto_properties_csv.split(",")
|
|
224
|
+
if options.data_governance_auto_properties_csv
|
|
225
|
+
else []
|
|
226
|
+
)
|
|
227
|
+
invalid_auto_props = [
|
|
228
|
+
_ for _ in auto_properties if not is_valid_data_governance_auto_property(_)
|
|
229
|
+
]
|
|
230
|
+
# TODO nj@2020-01-31 It feels like we should add the lines below but need to investigate/test before we do
|
|
231
|
+
# if invalid_auto_props:
|
|
232
|
+
# raise OrchestrationConfigException('Invalid values for DATA_GOVERNANCE_AUTO_PROPERTIES: %s'
|
|
233
|
+
# % invalid_auto_props)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def normalise_filesystem_options(options, exc_cls=OrchestrationConfigException):
|
|
237
|
+
options.offload_fs_scheme = (
|
|
238
|
+
options.offload_fs_scheme.lower()
|
|
239
|
+
if options.offload_fs_scheme
|
|
240
|
+
else options.offload_fs_scheme
|
|
241
|
+
)
|
|
242
|
+
if (
|
|
243
|
+
options.offload_fs_scheme
|
|
244
|
+
and options.offload_fs_scheme not in VALID_OFFLOAD_FS_SCHEMES
|
|
245
|
+
):
|
|
246
|
+
raise exc_cls(
|
|
247
|
+
"OFFLOAD_FS_SCHEME/--offload-fs-scheme must be one of: %s"
|
|
248
|
+
% VALID_OFFLOAD_FS_SCHEMES
|
|
249
|
+
)
|
|
250
|
+
if (
|
|
251
|
+
options.offload_fs_scheme in OFFLOAD_FS_SCHEMES_REQUIRING_CONTAINER
|
|
252
|
+
and not options.offload_fs_container
|
|
253
|
+
):
|
|
254
|
+
raise exc_cls(
|
|
255
|
+
"OFFLOAD_FS_CONTAINER/--offload-fs-container required for scheme: %s"
|
|
256
|
+
% options.offload_fs_scheme
|
|
257
|
+
)
|
|
258
|
+
if (
|
|
259
|
+
options.offload_fs_scheme == OFFLOAD_FS_SCHEME_MAPRFS
|
|
260
|
+
and options.backend_distribution != BACKEND_DISTRO_MAPR
|
|
261
|
+
):
|
|
262
|
+
raise exc_cls(
|
|
263
|
+
"OFFLOAD_FS_SCHEME/--offload-fs-scheme %s not valid for this backend system"
|
|
264
|
+
% options.offload_fs_scheme
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
if options.backend_distribution in HADOOP_BASED_BACKEND_DISTRIBUTIONS:
|
|
268
|
+
if not options.hdfs_data:
|
|
269
|
+
raise exc_cls("HDFS_DATA environment variable is mandatory")
|
|
270
|
+
if not options.hdfs_load:
|
|
271
|
+
raise exc_cls("HDFS_LOAD environment variable is mandatory")
|
|
272
|
+
|
|
273
|
+
# Not ideal to hardcode SNOWFLAKE here but we don't have a backend_api in normalise* to get the supported schemes
|
|
274
|
+
if options.backend_distribution == BACKEND_DISTRO_SNOWFLAKE:
|
|
275
|
+
if (
|
|
276
|
+
options.offload_fs_scheme in AZURE_OFFLOAD_FS_SCHEMES
|
|
277
|
+
and not options.offload_fs_azure_account_name
|
|
278
|
+
):
|
|
279
|
+
raise exc_cls(
|
|
280
|
+
"OFFLOAD_FS_AZURE_ACCOUNT_NAME required for scheme: %s"
|
|
281
|
+
% options.offload_fs_azure_account_name
|
|
282
|
+
)
|
|
283
|
+
if (
|
|
284
|
+
options.offload_fs_scheme in AZURE_OFFLOAD_FS_SCHEMES
|
|
285
|
+
and not options.offload_fs_azure_account_key
|
|
286
|
+
):
|
|
287
|
+
raise exc_cls(
|
|
288
|
+
"OFFLOAD_FS_AZURE_ACCOUNT_KEY required for scheme: %s"
|
|
289
|
+
% options.offload_fs_azure_account_key
|
|
290
|
+
)
|
|
291
|
+
if (
|
|
292
|
+
options.offload_fs_azure_account_domain
|
|
293
|
+
and not options.offload_fs_azure_account_domain.startswith(".")
|
|
294
|
+
):
|
|
295
|
+
options.offload_fs_azure_account_domain = (
|
|
296
|
+
"." + options.offload_fs_azure_account_domain
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
def normalise_listener_options(options):
|
|
301
|
+
# Listener options
|
|
302
|
+
if options.listener_port:
|
|
303
|
+
options.listener_port = orchestration_defaults.posint_option_from_string(
|
|
304
|
+
"OFFLOAD_LISTENER_PORT", options.listener_port
|
|
305
|
+
)
|
|
306
|
+
if options.listener_heartbeat_interval:
|
|
307
|
+
options.listener_heartbeat_interval = (
|
|
308
|
+
orchestration_defaults.posint_option_from_string(
|
|
309
|
+
"OFFLOAD_LISTENER_HEARTBEAT_INTERVAL",
|
|
310
|
+
options.listener_heartbeat_interval,
|
|
311
|
+
)
|
|
312
|
+
)
|
|
313
|
+
if options.password_key_file:
|
|
314
|
+
pass_tool = PasswordTools()
|
|
315
|
+
goe_key = pass_tool.get_password_key_from_key_file(options.password_key_file)
|
|
316
|
+
if options.listener_shared_token:
|
|
317
|
+
options.listener_shared_token = pass_tool.b64decrypt(
|
|
318
|
+
options.listener_shared_token, goe_key
|
|
319
|
+
)
|
|
320
|
+
if options.listener_redis_password:
|
|
321
|
+
options.listener_redis_password = pass_tool.b64decrypt(
|
|
322
|
+
options.listener_redis_password, goe_key
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
def normalise_offload_transport_config(options, exc_cls=OrchestrationConfigException):
|
|
327
|
+
def simple_file_csv(var_val, var_name):
|
|
328
|
+
"""Check for invalid characters that could be a shell injection risk."""
|
|
329
|
+
if not re.match(r"^[a-z0-9\/_\-:.,]+$", var_val):
|
|
330
|
+
raise exc_cls(f"Invalid characters found in {var_name}: {var_val}")
|
|
331
|
+
|
|
332
|
+
# Spark config
|
|
333
|
+
verify_json_option(
|
|
334
|
+
"OFFLOAD_TRANSPORT_RDBMS_SESSION_PARAMETERS",
|
|
335
|
+
options.offload_transport_rdbms_session_parameters,
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
if (
|
|
339
|
+
options.offload_transport_spark_submit_executable
|
|
340
|
+
and options.offload_transport_spark_submit_executable
|
|
341
|
+
not in VALID_SPARK_SUBMIT_EXECUTABLES
|
|
342
|
+
):
|
|
343
|
+
raise exc_cls(
|
|
344
|
+
"Invalid value for OFFLOAD_TRANSPORT_SPARK_SUBMIT_EXECUTABLE: %s"
|
|
345
|
+
% options.offload_transport_spark_submit_executable
|
|
346
|
+
)
|
|
347
|
+
if options.offload_transport_spark_submit_master_url and not (
|
|
348
|
+
options.offload_transport_spark_submit_master_url
|
|
349
|
+
== SPARK_SUBMIT_SPARK_YARN_MASTER
|
|
350
|
+
or re.match(
|
|
351
|
+
r"^local(\[[0-9]\])?$", options.offload_transport_spark_submit_master_url
|
|
352
|
+
)
|
|
353
|
+
or re.match(
|
|
354
|
+
r"^(spark|mesos|k8s)://.+$",
|
|
355
|
+
options.offload_transport_spark_submit_master_url,
|
|
356
|
+
)
|
|
357
|
+
):
|
|
358
|
+
raise exc_cls(
|
|
359
|
+
"Invalid value for OFFLOAD_TRANSPORT_SPARK_SUBMIT_MASTER_URL: %s"
|
|
360
|
+
% options.offload_transport_spark_submit_master_url
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
if options.offload_transport_spark_files:
|
|
364
|
+
simple_file_csv(
|
|
365
|
+
options.offload_transport_spark_files, "OFFLOAD_TRANSPORT_SPARK_FILES"
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
if options.offload_transport_spark_jars:
|
|
369
|
+
simple_file_csv(
|
|
370
|
+
options.offload_transport_spark_jars, "OFFLOAD_TRANSPORT_SPARK_JARS"
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
# Spark thriftserver config
|
|
374
|
+
if options.offload_transport_spark_thrift_host:
|
|
375
|
+
options.offload_transport_spark_thrift_host = random.choice(
|
|
376
|
+
options.offload_transport_spark_thrift_host.split(",")
|
|
377
|
+
)
|
|
378
|
+
if options.offload_transport_spark_thrift_port:
|
|
379
|
+
options.offload_transport_spark_thrift_port = (
|
|
380
|
+
orchestration_defaults.posint_option_from_string(
|
|
381
|
+
"OFFLOAD_TRANSPORT_SPARK_THRIFT_PORT",
|
|
382
|
+
options.offload_transport_spark_thrift_port,
|
|
383
|
+
)
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
# Livy config
|
|
387
|
+
if (
|
|
388
|
+
type(options.offload_transport_livy_api_verify_ssl) is not bool
|
|
389
|
+
and options.offload_transport_livy_api_verify_ssl is not None
|
|
390
|
+
):
|
|
391
|
+
options.offload_transport_livy_api_verify_ssl = str(
|
|
392
|
+
options.offload_transport_livy_api_verify_ssl
|
|
393
|
+
).strip()
|
|
394
|
+
if options.offload_transport_livy_api_verify_ssl == "":
|
|
395
|
+
options.offload_transport_livy_api_verify_ssl = None
|
|
396
|
+
elif options.offload_transport_livy_api_verify_ssl.lower() in ["true", "false"]:
|
|
397
|
+
options.offload_transport_livy_api_verify_ssl = bool(
|
|
398
|
+
options.offload_transport_livy_api_verify_ssl.lower() == "true"
|
|
399
|
+
)
|
|
400
|
+
if options.offload_transport_livy_api_verify_ssl is None:
|
|
401
|
+
options.offload_transport_livy_api_verify_ssl = (
|
|
402
|
+
derive_rest_api_verify_value_from_url(
|
|
403
|
+
options.offload_transport_livy_api_url
|
|
404
|
+
)
|
|
405
|
+
)
|
|
406
|
+
options.offload_transport_livy_max_sessions = (
|
|
407
|
+
orchestration_defaults.posint_option_from_string(
|
|
408
|
+
"OFFLOAD_TRANSPORT_LIVY_MAX_SESSIONS",
|
|
409
|
+
options.offload_transport_livy_max_sessions,
|
|
410
|
+
)
|
|
411
|
+
)
|
|
412
|
+
options.offload_transport_livy_idle_session_timeout = (
|
|
413
|
+
orchestration_defaults.posint_option_from_string(
|
|
414
|
+
"OFFLOAD_TRANSPORT_LIVY_IDLE_SESSION_TIMEOUT",
|
|
415
|
+
options.offload_transport_livy_idle_session_timeout,
|
|
416
|
+
)
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
# Generic transport config
|
|
420
|
+
if options.offload_transport:
|
|
421
|
+
options.offload_transport = options.offload_transport.upper()
|
|
422
|
+
if (
|
|
423
|
+
not options.offload_transport
|
|
424
|
+
or options.offload_transport not in VALID_OFFLOAD_TRANSPORTS
|
|
425
|
+
):
|
|
426
|
+
raise exc_cls(
|
|
427
|
+
"Invalid value for OFFLOAD_TRANSPORT/--offload-transport: %s"
|
|
428
|
+
% options.offload_transport
|
|
429
|
+
)
|
|
430
|
+
options.offload_transport_cmd_host = (
|
|
431
|
+
options.offload_transport_cmd_host or options.hdfs_host
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
if not options.offload_transport_dsn:
|
|
435
|
+
if options.db_type == DBTYPE_MSSQL:
|
|
436
|
+
options.offload_transport_dsn = options.mssql_dsn
|
|
437
|
+
elif options.db_type == DBTYPE_ORACLE:
|
|
438
|
+
options.offload_transport_dsn = options.oracle_dsn
|
|
439
|
+
elif options.db_type == DBTYPE_TERADATA:
|
|
440
|
+
options.offload_transport_dsn = options.teradata_server
|
|
441
|
+
|
|
442
|
+
if options.offload_staging_format:
|
|
443
|
+
options.offload_staging_format = options.offload_staging_format.upper()
|
|
444
|
+
|
|
445
|
+
# For backward compatibility
|
|
446
|
+
options.offload_transport_user = (
|
|
447
|
+
options.offload_transport_user or options.hadoop_ssh_user
|
|
448
|
+
)
|
|
449
|
+
if not options.offload_transport_user:
|
|
450
|
+
raise exc_cls("OFFLOAD_TRANSPORT_USER is mandatory")
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
def normalise_rdbms_options(options, exc_cls=OrchestrationConfigException):
|
|
454
|
+
if not options.db_type:
|
|
455
|
+
options.db_type = orchestration_defaults.frontend_db_type_default()
|
|
456
|
+
if getattr(options, "use_oracle_wallet", None) is None:
|
|
457
|
+
options.use_oracle_wallet = False
|
|
458
|
+
# Source vendor specifics
|
|
459
|
+
if options.db_type == DBTYPE_MSSQL:
|
|
460
|
+
normalise_mssql_options(options, exc_cls=exc_cls)
|
|
461
|
+
elif options.db_type == DBTYPE_ORACLE:
|
|
462
|
+
normalise_rdbms_oracle_options(options, exc_cls=exc_cls)
|
|
463
|
+
elif options.db_type == DBTYPE_TERADATA:
|
|
464
|
+
normalise_teradata_options(options, exc_cls=exc_cls)
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
def normalise_rdbms_oracle_options(options, exc_cls=OrchestrationConfigException):
|
|
468
|
+
"""Process Oracle connection options
|
|
469
|
+
silent is required when this is called before options has been defined, we don't want to try logging anything
|
|
470
|
+
before logging is ready.
|
|
471
|
+
"""
|
|
472
|
+
if not options.oracle_dsn:
|
|
473
|
+
raise exc_cls("Oracle connection options required")
|
|
474
|
+
elif not options.use_oracle_wallet and (
|
|
475
|
+
not options.ora_adm_user
|
|
476
|
+
or not options.ora_adm_pass
|
|
477
|
+
or not options.ora_app_user
|
|
478
|
+
or not options.ora_app_pass
|
|
479
|
+
):
|
|
480
|
+
raise exc_cls(
|
|
481
|
+
"Oracle username and password must be supplied for app and admin users unless Oracle Wallet is used"
|
|
482
|
+
)
|
|
483
|
+
elif not options.ora_repo_user:
|
|
484
|
+
raise exc_cls("Oracle repository username required")
|
|
485
|
+
|
|
486
|
+
options.rdbms_app_user = options.ora_app_user
|
|
487
|
+
options.rdbms_app_pass = options.ora_app_pass
|
|
488
|
+
if options.oracle_adm_dsn:
|
|
489
|
+
options.rdbms_dsn = options.oracle_adm_dsn
|
|
490
|
+
else:
|
|
491
|
+
options.rdbms_dsn = options.oracle_dsn
|
|
492
|
+
|
|
493
|
+
if not options.password_key_file:
|
|
494
|
+
return
|
|
495
|
+
pass_tool = PasswordTools()
|
|
496
|
+
goe_key = pass_tool.get_password_key_from_key_file(options.password_key_file)
|
|
497
|
+
options.rdbms_app_pass = options.ora_app_pass = pass_tool.b64decrypt(
|
|
498
|
+
options.rdbms_app_pass, goe_key
|
|
499
|
+
)
|
|
500
|
+
options.ora_adm_pass = pass_tool.b64decrypt(options.ora_adm_pass, goe_key)
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
def normalise_rdbms_wallet_options(options, frontend_api=None):
|
|
504
|
+
if options.use_oracle_wallet:
|
|
505
|
+
if frontend_api:
|
|
506
|
+
# We need to set/override ora_adm_user when using Oracle Wallet
|
|
507
|
+
options.ora_adm_user = frontend_api.get_session_user()
|
|
508
|
+
options.offload_transport_auth_using_oracle_wallet = True
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
def normalise_mssql_options(options, exc_cls=OrchestrationConfigException):
|
|
512
|
+
if (
|
|
513
|
+
not options.mssql_app_user
|
|
514
|
+
or not options.mssql_app_pass
|
|
515
|
+
or not options.mssql_dsn
|
|
516
|
+
):
|
|
517
|
+
raise exc_cls("Microsoft SQL Server connection options required")
|
|
518
|
+
|
|
519
|
+
options.rdbms_app_user = options.mssql_app_user
|
|
520
|
+
options.rdbms_app_pass = options.mssql_app_pass
|
|
521
|
+
options.rdbms_dsn = options.mssql_dsn
|
|
522
|
+
options.ora_adm_user = None
|
|
523
|
+
options.ora_adm_pass = None
|
|
524
|
+
options.ora_repo_user = None
|
|
525
|
+
options.sqoop_password_file = None
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
def normalise_teradata_options(options, exc_cls=OrchestrationConfigException):
|
|
529
|
+
if (
|
|
530
|
+
not options.teradata_adm_user
|
|
531
|
+
or not options.teradata_adm_pass
|
|
532
|
+
or not options.teradata_server
|
|
533
|
+
):
|
|
534
|
+
raise exc_cls("Teradata connection options required")
|
|
535
|
+
if not options.teradata_app_user or not options.teradata_app_pass:
|
|
536
|
+
raise exc_cls("Teradata connection options required")
|
|
537
|
+
if not options.teradata_repo_user:
|
|
538
|
+
raise exc_cls("Teradata repository username required")
|
|
539
|
+
|
|
540
|
+
options.rdbms_app_user = options.teradata_app_user
|
|
541
|
+
options.rdbms_app_pass = options.teradata_app_pass
|
|
542
|
+
options.rdbms_dsn = options.teradata_server
|
|
543
|
+
|
|
544
|
+
if not options.frontend_odbc_driver_name:
|
|
545
|
+
raise exc_cls("FRONTEND_ODBC_DRIVER_NAME is required for Teradata connections")
|
|
546
|
+
|
|
547
|
+
if not options.password_key_file:
|
|
548
|
+
return
|
|
549
|
+
pass_tool = PasswordTools()
|
|
550
|
+
goe_key = pass_tool.get_password_key_from_key_file(options.password_key_file)
|
|
551
|
+
options.rdbms_app_pass = options.teradata_app_pass = pass_tool.b64decrypt(
|
|
552
|
+
options.teradata_app_pass, goe_key
|
|
553
|
+
)
|
|
554
|
+
options.teradata_adm_pass = pass_tool.b64decrypt(options.teradata_adm_pass, goe_key)
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
def normalise_size_option(
|
|
558
|
+
opt_val, binary_sizes=False, strict_name=None, exc_cls=OrchestrationConfigException
|
|
559
|
+
):
|
|
560
|
+
"""strict_name can be used to raise an exception if incorrectly formatted inputs are
|
|
561
|
+
passed in. Otherwise we just return 0.
|
|
562
|
+
strict_name is the name of the option to include in the exception
|
|
563
|
+
"""
|
|
564
|
+
if opt_val and type(opt_val) is str:
|
|
565
|
+
new_val = opt_val.upper() if opt_val else None
|
|
566
|
+
else:
|
|
567
|
+
new_val = opt_val
|
|
568
|
+
new_val = human_size_to_bytes(new_val, binary_sizes=binary_sizes)
|
|
569
|
+
if strict_name and new_val is None:
|
|
570
|
+
raise exc_cls("Invalid %s: %s" % (strict_name, opt_val))
|
|
571
|
+
return new_val or 0
|
|
572
|
+
|
|
573
|
+
|
|
574
|
+
def normalise_snowflake_options(options, exc_cls=OrchestrationConfigException):
|
|
575
|
+
if options.backend_distribution != BACKEND_DISTRO_SNOWFLAKE:
|
|
576
|
+
return
|
|
577
|
+
if not options.snowflake_user:
|
|
578
|
+
raise exc_cls("SNOWFLAKE_USER is mandatory")
|
|
579
|
+
if not options.snowflake_pass and not options.snowflake_pem_file:
|
|
580
|
+
raise exc_cls("Either SNOWFLAKE_PASS or SNOWFLAKE_PEM_FILE is required")
|
|
581
|
+
if not options.snowflake_account:
|
|
582
|
+
raise exc_cls("SNOWFLAKE_ACCOUNT is mandatory")
|
|
583
|
+
if not options.snowflake_database:
|
|
584
|
+
raise exc_cls("SNOWFLAKE_DATABASE is mandatory")
|
|
585
|
+
if not options.snowflake_file_format_prefix:
|
|
586
|
+
raise exc_cls("SNOWFLAKE_FILE_FORMAT_PREFIX is mandatory")
|
|
587
|
+
if not options.snowflake_integration:
|
|
588
|
+
raise exc_cls("SNOWFLAKE_INTEGRATION is mandatory")
|
|
589
|
+
if not options.snowflake_role:
|
|
590
|
+
raise exc_cls("SNOWFLAKE_ROLE is mandatory")
|
|
591
|
+
if not options.snowflake_stage:
|
|
592
|
+
raise exc_cls("SNOWFLAKE_STAGE is mandatory")
|
|
593
|
+
if not options.snowflake_warehouse:
|
|
594
|
+
raise exc_cls("SNOWFLAKE_WAREHOUSE is mandatory")
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
def normalise_synapse_options(options, exc_cls=OrchestrationConfigException):
|
|
598
|
+
if options.backend_distribution != BACKEND_DISTRO_MSAZURE:
|
|
599
|
+
return
|
|
600
|
+
if not options.synapse_auth_mechanism:
|
|
601
|
+
raise exc_cls("SYNAPSE_AUTH_MECHANISM is mandatory")
|
|
602
|
+
if options.synapse_auth_mechanism not in SYNAPSE_VALID_AUTH_MECHANISMS:
|
|
603
|
+
raise exc_cls(
|
|
604
|
+
"Invalid value for SYNAPSE_AUTH_MECHANISM: %s. Must be one of: %s"
|
|
605
|
+
% (options.synapse_auth_mechanism, ", ".join(SYNAPSE_VALID_AUTH_MECHANISMS))
|
|
606
|
+
)
|
|
607
|
+
if options.synapse_auth_mechanism in SYNAPSE_USER_PASS_AUTH_MECHANISMS:
|
|
608
|
+
if not options.synapse_user:
|
|
609
|
+
raise exc_cls("SYNAPSE_USER is mandatory")
|
|
610
|
+
if not options.synapse_pass:
|
|
611
|
+
raise exc_cls("SYNAPSE_PASS is mandatory")
|
|
612
|
+
if options.synapse_auth_mechanism == SYNAPSE_AUTH_MECHANISM_AD_SERVICE_PRINCIPAL:
|
|
613
|
+
if not options.synapse_service_principal_id:
|
|
614
|
+
raise exc_cls("SYNAPSE_SERVICE_PRINCIPAL_ID is mandatory")
|
|
615
|
+
if not options.synapse_service_principal_secret:
|
|
616
|
+
raise exc_cls("SYNAPSE_SERVICE_PRINCIPAL_SECRET is mandatory")
|
|
617
|
+
if not options.synapse_server:
|
|
618
|
+
raise exc_cls("SYNAPSE_SERVER is mandatory")
|
|
619
|
+
if not options.synapse_database:
|
|
620
|
+
raise exc_cls("SYNAPSE_DATABASE is mandatory")
|
|
621
|
+
if not options.synapse_port:
|
|
622
|
+
raise exc_cls("SYNAPSE_PORT is mandatory")
|
|
623
|
+
if not options.synapse_data_source:
|
|
624
|
+
raise exc_cls("SYNAPSE_DATA_SOURCE is mandatory")
|
|
625
|
+
if not options.synapse_file_format:
|
|
626
|
+
raise exc_cls("SYNAPSE_FILE_FORMAT is mandatory")
|
|
627
|
+
if not options.synapse_role:
|
|
628
|
+
raise exc_cls("SYNAPSE_ROLE is mandatory")
|
|
629
|
+
if not options.backend_odbc_driver_name:
|
|
630
|
+
raise exc_cls("BACKEND_ODBC_DRIVER_NAME is mandatory")
|
|
631
|
+
|
|
632
|
+
|
|
633
|
+
def normalise_webhdfs(options):
|
|
634
|
+
def webhdfs_default_port(webhdfs_verify_ssl):
|
|
635
|
+
default_http_port = 50070
|
|
636
|
+
default_https_port = 50470
|
|
637
|
+
return default_http_port if webhdfs_verify_ssl is None else default_https_port
|
|
638
|
+
|
|
639
|
+
if isinstance(options.webhdfs_verify_ssl, bool):
|
|
640
|
+
return
|
|
641
|
+
if options.webhdfs_verify_ssl is not None:
|
|
642
|
+
if options.webhdfs_verify_ssl.lower() in ["true", "false"]:
|
|
643
|
+
options.webhdfs_verify_ssl = (
|
|
644
|
+
True if options.webhdfs_verify_ssl.lower() == "true" else False
|
|
645
|
+
)
|
|
646
|
+
elif not str(options.webhdfs_verify_ssl).strip():
|
|
647
|
+
options.webhdfs_verify_ssl = None
|
|
648
|
+
|
|
649
|
+
options.webhdfs_port = (
|
|
650
|
+
options.webhdfs_port
|
|
651
|
+
or orchestration_defaults.webhdfs_port_default()
|
|
652
|
+
or webhdfs_default_port(options.webhdfs_verify_ssl)
|
|
653
|
+
)
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
def check_offload_fs_scheme_supported_in_backend(offload_fs_scheme, backend_api):
|
|
657
|
+
if offload_fs_scheme not in backend_api.valid_offload_fs_schemes():
|
|
658
|
+
display_version = backend_api.target_version()
|
|
659
|
+
display_version = " ({})".format(display_version) if display_version else ""
|
|
660
|
+
raise OrchestrationConfigException(
|
|
661
|
+
"Offload to %s%s does not support filesystem scheme: %s"
|
|
662
|
+
% (backend_api.backend_db_name(), display_version, offload_fs_scheme)
|
|
663
|
+
)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#! /usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
# Copyright 2016 The GOE Authors. All rights reserved.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
""" option_descriptions: Library of constants defining descriptions for options.
|
|
18
|
+
In the future we expect to refactor all option processing, including descriptions, and this module will
|
|
19
|
+
may become redundant at that time.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
DATA_SAMPLE_PARALLELISM = (
|
|
23
|
+
"Degree of parallelism to use when sampling RDBMS data for columns with no precision/scale properties. "
|
|
24
|
+
"Values of 0 or 1 will execute the query without parallelism"
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
RESET_BACKEND_TABLE = "Remove backend data table. Use with caution - this will delete previously offloaded data for this table!"
|
|
28
|
+
|
|
29
|
+
REUSE_BACKEND_TABLE = (
|
|
30
|
+
"Allow Offload to re-use an empty backend table when there is already Offload metadata. "
|
|
31
|
+
"This may be useful if a backend table had data removed by an administrator and a re-offload is required"
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
VERIFY_PARALLELISM = (
|
|
35
|
+
"Degree of parallelism to use for the RDBMS query executed when validating an offload. "
|
|
36
|
+
"Values of 0 or 1 will execute the query without parallelism. Values > 1 will force a parallel query of the given degree. "
|
|
37
|
+
"If unset, the RDBMS query will fall back to using the behavior specified by RDBMS defaults"
|
|
38
|
+
)
|