fivetran-connector-sdk 1.1.2__tar.gz → 1.1.4__tar.gz

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.
Files changed (18) hide show
  1. {fivetran_connector_sdk-1.1.2 → fivetran_connector_sdk-1.1.4}/PKG-INFO +1 -1
  2. {fivetran_connector_sdk-1.1.2 → fivetran_connector_sdk-1.1.4}/src/fivetran_connector_sdk/__init__.py +99 -35
  3. {fivetran_connector_sdk-1.1.2 → fivetran_connector_sdk-1.1.4}/src/fivetran_connector_sdk.egg-info/PKG-INFO +1 -1
  4. {fivetran_connector_sdk-1.1.2 → fivetran_connector_sdk-1.1.4}/README.md +0 -0
  5. {fivetran_connector_sdk-1.1.2 → fivetran_connector_sdk-1.1.4}/pyproject.toml +0 -0
  6. {fivetran_connector_sdk-1.1.2 → fivetran_connector_sdk-1.1.4}/setup.cfg +0 -0
  7. {fivetran_connector_sdk-1.1.2 → fivetran_connector_sdk-1.1.4}/src/fivetran_connector_sdk/protos/__init__.py +0 -0
  8. {fivetran_connector_sdk-1.1.2 → fivetran_connector_sdk-1.1.4}/src/fivetran_connector_sdk/protos/common_pb2.py +0 -0
  9. {fivetran_connector_sdk-1.1.2 → fivetran_connector_sdk-1.1.4}/src/fivetran_connector_sdk/protos/common_pb2.pyi +0 -0
  10. {fivetran_connector_sdk-1.1.2 → fivetran_connector_sdk-1.1.4}/src/fivetran_connector_sdk/protos/common_pb2_grpc.py +0 -0
  11. {fivetran_connector_sdk-1.1.2 → fivetran_connector_sdk-1.1.4}/src/fivetran_connector_sdk/protos/connector_sdk_pb2.py +0 -0
  12. {fivetran_connector_sdk-1.1.2 → fivetran_connector_sdk-1.1.4}/src/fivetran_connector_sdk/protos/connector_sdk_pb2.pyi +0 -0
  13. {fivetran_connector_sdk-1.1.2 → fivetran_connector_sdk-1.1.4}/src/fivetran_connector_sdk/protos/connector_sdk_pb2_grpc.py +0 -0
  14. {fivetran_connector_sdk-1.1.2 → fivetran_connector_sdk-1.1.4}/src/fivetran_connector_sdk.egg-info/SOURCES.txt +0 -0
  15. {fivetran_connector_sdk-1.1.2 → fivetran_connector_sdk-1.1.4}/src/fivetran_connector_sdk.egg-info/dependency_links.txt +0 -0
  16. {fivetran_connector_sdk-1.1.2 → fivetran_connector_sdk-1.1.4}/src/fivetran_connector_sdk.egg-info/entry_points.txt +0 -0
  17. {fivetran_connector_sdk-1.1.2 → fivetran_connector_sdk-1.1.4}/src/fivetran_connector_sdk.egg-info/requires.txt +0 -0
  18. {fivetran_connector_sdk-1.1.2 → fivetran_connector_sdk-1.1.4}/src/fivetran_connector_sdk.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: fivetran_connector_sdk
3
- Version: 1.1.2
3
+ Version: 1.1.4
4
4
  Summary: Build custom connectors on Fivetran platform
5
5
  Author-email: Fivetran <developers@fivetran.com>
6
6
  Project-URL: Homepage, https://fivetran.com/docs/connectors/connector-sdk
@@ -23,6 +23,7 @@ from datetime import datetime
23
23
  from enum import IntEnum
24
24
  from google.protobuf import timestamp_pb2
25
25
  from zipfile import ZipFile, ZIP_DEFLATED
26
+ from http import HTTPStatus
26
27
 
27
28
  from fivetran_connector_sdk.protos import common_pb2
28
29
  from fivetran_connector_sdk.protos import connector_sdk_pb2
@@ -30,13 +31,13 @@ from fivetran_connector_sdk.protos import connector_sdk_pb2_grpc
30
31
 
31
32
  # Version format: <major_version>.<minor_version>.<patch_version>
32
33
  # (where Major Version = 1 for GA, Minor Version is incremental MM from Jan 25 onwards, Patch Version is incremental within a month)
33
- __version__ = "1.1.2"
34
+ __version__ = "1.1.4"
34
35
 
35
36
  MAC_OS = "mac"
36
37
  WIN_OS = "windows"
37
38
  LINUX_OS = "linux"
38
39
 
39
- TESTER_VERSION = "0.25.0130.001"
40
+ TESTER_VERSION = "0.25.0225.001"
40
41
  TESTER_FILENAME = "run_sdk_tester.jar"
41
42
  VERSION_FILENAME = "version.txt"
42
43
  UPLOAD_FILENAME = "code.zip"
@@ -76,7 +77,7 @@ INSTALLATION_SCRIPT = "installation.sh"
76
77
  DRIVERS = "drivers"
77
78
  JAVA_LONG_MAX_VALUE = 9223372036854775807
78
79
  MAX_CONFIG_FIELDS = 100
79
- SUPPORTED_PYTHON_VERSIONS = {"3.12.8", "3.11.11", "3.10.16", "3.9.21"}
80
+ SUPPORTED_PYTHON_VERSIONS = ["3.12.8", "3.11.11", "3.10.16", "3.9.21"]
80
81
  DEFAULT_PYTHON_VERSION = "3.12.8"
81
82
  FIVETRAN_HD_AGENT_ID = "FIVETRAN_HD_AGENT_ID"
82
83
 
@@ -502,12 +503,12 @@ def validate_deploy_parameters(connection, deploy_key, python_version):
502
503
  "\t\t--destination <DESTINATION_NAME> (Becomes required if there are multiple destinations)\n"
503
504
  "\t\t--configuration <CONFIGURATION_FILE> (Completely replaces the existing configuration)", Logging.Level.SEVERE)
504
505
  os._exit(1)
505
- if not is_connection_name_valid(connection):
506
+ elif not is_connection_name_valid(connection):
506
507
  print_library_log(f"Connection name: {connection} is invalid!\n The connection name should start with an "
507
508
  f"underscore or a lowercase letter (a-z), followed by any combination of underscores, lowercase "
508
509
  f"letters, or digits (0-9). Uppercase characters are not allowed.", Logging.Level.SEVERE)
509
510
  os._exit(1)
510
- if python_version and python_version not in SUPPORTED_PYTHON_VERSIONS:
511
+ elif python_version and python_version not in SUPPORTED_PYTHON_VERSIONS:
511
512
  print_library_log(f"This Python version is not supported: {python_version}. "
512
513
  f"We only support the following python versions: {SUPPORTED_PYTHON_VERSIONS} ", Logging.Level.SEVERE)
513
514
  os._exit(1)
@@ -774,29 +775,48 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
774
775
  if version_mismatch_deps:
775
776
  print_library_log("We recommend using the current stable version for the following:", Logging.Level.WARNING)
776
777
  print(version_mismatch_deps)
778
+ if is_deploy and not force:
779
+ confirm = input(
780
+ f"Would you like us to update {REQUIREMENTS_TXT} to the current stable versions of the dependent libraries? (Y/N):")
781
+ if confirm.lower() == "y":
782
+ for requirement in version_mismatch_deps:
783
+ requirements[requirement] = tmp_requirements[requirement]
777
784
 
778
785
  missing_deps = {key: tmp_requirements[key] for key in (tmp_requirements.keys() - requirements.keys())}
779
786
  if missing_deps:
780
787
  self.handle_missing_deps(missing_deps)
788
+ if is_deploy and not force:
789
+ confirm = input(
790
+ f"Would you like us to update {REQUIREMENTS_TXT} to add missing dependent libraries? (Y/N):")
791
+ if confirm.lower() == "n":
792
+ print_library_log(f"Please fix your {REQUIREMENTS_TXT} file to proceed with deployment.")
793
+ os._exit(1)
794
+ elif confirm.lower() == "y":
795
+ for requirement in missing_deps:
796
+ requirements[requirement] = tmp_requirements[requirement]
781
797
 
782
798
  unused_deps = list(requirements.keys() - tmp_requirements.keys())
783
799
  if unused_deps:
784
800
  self.handle_unused_deps(unused_deps)
801
+ if is_deploy and not force:
802
+ confirm = input(f"Would you like us to update {REQUIREMENTS_TXT} to remove the unused libraries? (Y/N):")
803
+ if confirm.lower() == "n":
804
+ if 'fivetran_connector_sdk' in unused_deps or 'requests' in unused_deps:
805
+ print_library_log(f"Please fix your {REQUIREMENTS_TXT} file by removing pre-installed dependencies to proceed with deployment.")
806
+ os._exit(1)
807
+ elif confirm.lower() == "y":
808
+ for requirement in unused_deps:
809
+ del requirements[requirement]
810
+
785
811
 
786
812
  if is_deploy and (version_mismatch_deps or missing_deps or unused_deps):
787
813
  if force:
788
- confirm = "y"
789
- else:
790
- confirm = input("We detected issues in your requirements.txt. "
791
- "Would you like us to update it to reflect the necessary changes? (Y/N):")
792
- if confirm.lower() == "y":
793
- with open(REQUIREMENTS_TXT, "w") as file:
794
- file.write("\n".join(tmp_requirements.values()))
795
- print_library_log(f"`{REQUIREMENTS_TXT}` has been updated successfully")
796
- else:
797
- if missing_deps or 'fivetran_connector_sdk' in unused_deps or 'requests' in unused_deps:
798
- print_library_log(f"Please fix your {REQUIREMENTS_TXT} file to proceed with deployment.")
799
- os._exit(1)
814
+ requirements = tmp_requirements
815
+
816
+ with open(REQUIREMENTS_TXT, "w") as file:
817
+ file.write("\n".join(requirements.values()))
818
+ print_library_log(f"`{REQUIREMENTS_TXT}` has been updated successfully")
819
+
800
820
  else:
801
821
  if os.path.exists(REQUIREMENTS_TXT):
802
822
  print_library_log("`requirements.txt` is not required as no additional "
@@ -808,15 +828,14 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
808
828
  def handle_unused_deps(self, unused_deps):
809
829
  if 'fivetran_connector_sdk' in unused_deps:
810
830
  log_unused_deps_error("fivetran_connector_sdk", __version__)
811
- elif 'requests' in unused_deps:
831
+ if 'requests' in unused_deps:
812
832
  log_unused_deps_error("requests", "2.32.3")
813
- else:
814
- print_library_log("The following dependencies are not needed, "
815
- "they are not used or already installed. Please remove them from requirements.txt:")
816
- print(*unused_deps)
833
+ print_library_log("The following dependencies are not needed, "
834
+ f"they are not used or already installed. Please remove them from {REQUIREMENTS_TXT}:")
835
+ print(*unused_deps)
817
836
 
818
837
  def handle_missing_deps(self, missing_deps):
819
- print_library_log("Please include the following dependency libraries in requirements.txt, to be used by "
838
+ print_library_log(f"Please include the following dependency libraries in {REQUIREMENTS_TXT}, to be used by "
820
839
  "Fivetran production. "
821
840
  "For more information, please visit: "
822
841
  "https://fivetran.com/docs/connectors/connector-sdk/detailed-guide"
@@ -909,15 +928,18 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
909
928
  group_id, group_name, connection)
910
929
  response = self.__create_connection(
911
930
  deploy_key, group_id, connection_config, hd_agent_id)
912
- if response.ok:
913
- print_library_log(
914
- f"The connection '{connection}' has been created successfully.\n")
915
- connection_id = response.json()['data']['id']
916
- # Python Version is not passed into connection_config as default value will be picked up from ConnectorSdkCredentials.java class.
917
- print_library_log(f"Python Version: {args.python_version if args.python_version else DEFAULT_PYTHON_VERSION}", Logging.Level.INFO)
918
- print_library_log(f"Connector ID: {connection_id}")
919
- print_library_log(
920
- f"Visit the Fivetran dashboard to start the initial sync: https://fivetran.com/dashboard/connectors/{connection_id}/status")
931
+ if response.ok and response.status_code == HTTPStatus.CREATED:
932
+ if Connector.__are_setup_tests_failing(response):
933
+ Connector.__handle_failing_tests_message_and_exit(response, "The connection was created, but setup tests failed!")
934
+ else:
935
+ print_library_log(
936
+ f"The connection '{connection}' has been created successfully.\n")
937
+ connection_id = response.json()['data']['id']
938
+ # Python Version is not passed into connection_config as default value will be picked up from ConnectorSdkCredentials.java class.
939
+ print_library_log(f"Python Version: {args.python_version if args.python_version else DEFAULT_PYTHON_VERSION}", Logging.Level.INFO)
940
+ print_library_log(f"Connector ID: {connection_id}")
941
+ print_library_log(
942
+ f"Visit the Fivetran dashboard to start the initial sync: https://fivetran.com/dashboard/connectors/{connection_id}/status")
921
943
  else:
922
944
  print_library_log(
923
945
  f"Unable to create a new connection, failed with error: {response.json()['message']}", Logging.Level.SEVERE)
@@ -956,7 +978,7 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
956
978
  if not args.configuration:
957
979
  del config["secrets_list"]
958
980
 
959
- resp = rq.patch(f"{PRODUCTION_BASE_URL}/v1/connectors/{id}",
981
+ response = rq.patch(f"{PRODUCTION_BASE_URL}/v1/connectors/{id}",
960
982
  headers={"Authorization": f"Basic {deploy_key}"},
961
983
  json={
962
984
  "config": config,
@@ -964,11 +986,53 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
964
986
  "run_setup_tests": True
965
987
  })
966
988
 
967
- if not resp.ok:
989
+ if response.ok and response.status_code == HTTPStatus.OK:
990
+ if Connector.__are_setup_tests_failing(response):
991
+ Connector.__handle_failing_tests_message_and_exit(response, "The connection was updated, but setup tests failed!")
992
+ else:
993
+ print_library_log(f"Connection '{name}' in group '{group}' updated successfully.", Logging.Level.INFO)
994
+
995
+ else:
968
996
  print_library_log(
969
- f"Unable to update Connection '{name}' in destination '{group}', failed with error: '{resp.json()['message']}'.", Logging.Level.SEVERE)
997
+ f"Unable to update Connection '{name}' in destination '{group}', failed with error: '{response.json()['message']}'.", Logging.Level.SEVERE)
970
998
  os._exit(1)
971
999
 
1000
+ @staticmethod
1001
+ def __handle_failing_tests_message_and_exit(resp, log_message):
1002
+ print_library_log(log_message, Logging.Level.SEVERE)
1003
+ Connector.__print_failing_setup_tests(resp)
1004
+ connection_id = resp.json().get('data', {}).get('id')
1005
+ print_library_log(f"Connector ID: {connection_id}")
1006
+ print_library_log("Please try again with the deploy command after resolving the issue!")
1007
+ os._exit(1)
1008
+
1009
+ @staticmethod
1010
+ def __are_setup_tests_failing(response) -> bool:
1011
+ """Checks for failed setup tests in the response and returns True if any test has failed, otherwise False."""
1012
+ response_json = response.json()
1013
+ setup_tests = response_json.get("data", {}).get("setup_tests", [])
1014
+
1015
+ # Return True if any test has "FAILED" status, otherwise False
1016
+ return any(test.get("status") == "FAILED" or test.get("status") == "JOB_FAILED" for test in setup_tests)
1017
+
1018
+
1019
+ @staticmethod
1020
+ def __print_failing_setup_tests(response):
1021
+ """Checks for failed setup tests in the response and print errors."""
1022
+ response_json = response.json()
1023
+ setup_tests = response_json.get("data", {}).get("setup_tests", [])
1024
+
1025
+ # Collect failed setup tests
1026
+ failed_tests = [test for test in setup_tests if test.get("status") == "FAILED" or test.get("status") == "JOB_FAILED"]
1027
+
1028
+ if failed_tests:
1029
+ print_library_log("Following setup tests have failed!", Logging.Level.WARNING)
1030
+ for test in failed_tests:
1031
+ print_library_log(f"Test: {test.get('title')}", Logging.Level.WARNING)
1032
+ print_library_log(f"Status: {test.get('status')}", Logging.Level.WARNING)
1033
+ print_library_log(f"Message: {test.get('message')}", Logging.Level.WARNING)
1034
+
1035
+
972
1036
  @staticmethod
973
1037
  def __get_connection_id(name: str, group: str, group_id: str, deploy_key: str) -> Optional[Tuple[str, str]]:
974
1038
  """Retrieves the connection ID for the specified connection schema name, group, and deployment key.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: fivetran_connector_sdk
3
- Version: 1.1.2
3
+ Version: 1.1.4
4
4
  Summary: Build custom connectors on Fivetran platform
5
5
  Author-email: Fivetran <developers@fivetran.com>
6
6
  Project-URL: Homepage, https://fivetran.com/docs/connectors/connector-sdk