Skip to content

Commit d4b6efc

Browse files
darynaishchenkoalafanecherelazebnyioctavia-squidington-iii
authored
feat(source-airtable): migrate to low-code (#49813)
Co-authored-by: alafanechere <[email protected]> Co-authored-by: Serhii Lazebnyi <[email protected]> Co-authored-by: Octavia Squidington III <[email protected]>
1 parent db04610 commit d4b6efc

29 files changed

+2735
-1916
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[run]
2+
omit =
3+
source_airtable/run.py

airbyte-integrations/connectors/source-airtable/acceptance-test-config.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ test_strictness_level: high
55
acceptance_tests:
66
spec:
77
tests:
8-
- spec_path: "source_airtable/spec.json"
8+
- spec_path: "integration_tests/spec.json"
99
connection:
1010
tests:
1111
- config_path: "secrets/config.json"

airbyte-integrations/connectors/source-airtable/source_airtable/spec.json airbyte-integrations/connectors/source-airtable/integration_tests/spec.json

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
{
2-
"documentationUrl": "https://docs.airbyte.com/integrations/sources/airtable",
32
"connectionSpecification": {
4-
"$schema": "https://json-schema.org/draft-07/schema#",
5-
"title": "Airtable Source Spec",
63
"type": "object",
7-
"additionalProperties": true,
4+
"$schema": "http://json-schema.org/draft-07/schema#",
85
"properties": {
96
"credentials": {
107
"title": "Authentication",
@@ -27,8 +24,8 @@
2724
},
2825
"client_secret": {
2926
"type": "string",
30-
"title": "Client secret",
31-
"description": "The client secret the Airtable developer application.",
27+
"title": "Client Secret",
28+
"description": "The client secret of the Airtable developer application.",
3229
"airbyte_secret": true
3330
},
3431
"access_token": {
@@ -50,8 +47,8 @@
5047
}
5148
},
5249
{
53-
"title": "Personal Access Token",
5450
"type": "object",
51+
"title": "Personal Access Token",
5552
"required": ["api_key"],
5653
"properties": {
5754
"auth_method": {
@@ -69,8 +66,11 @@
6966
}
7067
]
7168
}
72-
}
69+
},
70+
"additionalProperties": true
7371
},
72+
"supportsNormalization": false,
73+
"supportsDBT": false,
7474
"advanced_auth": {
7575
"auth_flow_type": "oauth2.0",
7676
"predicate_key": ["credentials", "auth_method"],

airbyte-integrations/connectors/source-airtable/metadata.yaml

+5-3
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ data:
77
- api.airtable.com
88
- airtable.com
99
connectorBuildOptions:
10-
baseImage: docker.io/airbyte/python-connector-base:2.0.0@sha256:c44839ba84406116e8ba68722a0f30e8f6e7056c726f447681bb9e9ece8bd916
10+
baseImage: docker.io/airbyte/python-connector-base:3.0.0@sha256:1a0845ff2b30eafa793c6eee4e8f4283c2e52e1bbd44eed6cb9e9abd5d34d844
1111
connectorSubtype: api
1212
connectorType: source
1313
definitionId: 14c6e7ea-97ed-4f5e-a7b5-25e9a80b8212
14-
dockerImageTag: 4.4.0
14+
dockerImageTag: 4.5.0-rc.1
1515
dockerRepository: airbyte/source-airtable
1616
documentationUrl: https://docs.airbyte.com/integrations/sources/airtable
1717
githubIssueLabel: source-airtable
@@ -34,10 +34,12 @@ data:
3434
4.0.0:
3535
message: This release introduces changes to columns with formula to parse values directly from `array` to `string` or `number` (where it is possible). Users should refresh the source schema and reset affected streams after upgrading to ensure uninterrupted syncs.
3636
upgradeDeadline: "2023-10-23"
37+
rolloutConfiguration:
38+
enableProgressiveRollout: true
3739
supportLevel: certified
3840
tags:
3941
- language:python
40-
- cdk:python
42+
- cdk:low-code
4143
connectorTestSuitesOptions:
4244
- suite: liveTests
4345
testConnections:

airbyte-integrations/connectors/source-airtable/poetry.lock

+1,246-637
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

airbyte-integrations/connectors/source-airtable/pyproject.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",]
33
build-backend = "poetry.core.masonry.api"
44

55
[tool.poetry]
6-
version = "4.4.0"
6+
version = "4.5.0-rc.1"
77
name = "source-airtable"
88
description = "Source implementation for Airtable."
99
authors = [ "Airbyte <[email protected]>",]
@@ -16,8 +16,8 @@ repository = "https://github.com/airbytehq/airbyte"
1616
include = "source_airtable"
1717

1818
[tool.poetry.dependencies]
19-
python = "^3.9,<3.12"
20-
airbyte-cdk = "^3"
19+
python = "^3.10,<3.12"
20+
airbyte-cdk = "^6"
2121

2222
[tool.poetry.scripts]
2323
source-airtable = "source_airtable.run:run"

airbyte-integrations/connectors/source-airtable/source_airtable/airtable_backoff_strategy.py

-26
This file was deleted.

airbyte-integrations/connectors/source-airtable/source_airtable/airtable_error_handler.py

-44
This file was deleted.

airbyte-integrations/connectors/source-airtable/source_airtable/airtable_error_mapping.py

-21
This file was deleted.

airbyte-integrations/connectors/source-airtable/source_airtable/auth.py

-69
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Copyright (c) 2024 Airbyte, Inc., all rights reserved.
2+
3+
from typing import Any, List, Mapping
4+
5+
import orjson
6+
7+
from airbyte_cdk.config_observation import create_connector_config_control_message
8+
from airbyte_cdk.entrypoint import AirbyteEntrypoint
9+
from airbyte_cdk.models import AirbyteMessageSerializer
10+
from airbyte_cdk.sources.message import InMemoryMessageRepository, MessageRepository
11+
from source_airtable import SourceAirtable
12+
13+
14+
class MigrateApiKey:
15+
"""
16+
Migrates old configs to a new supported format.
17+
18+
OLD:
19+
{
20+
"api_key": ...
21+
}
22+
23+
NEW:
24+
{
25+
"credentials": {"api_key": ..., "auth_method": "api_key"}
26+
}
27+
28+
"""
29+
30+
migrate_from_key = "api_key"
31+
migrate_to_key = "credentials"
32+
33+
message_repository: MessageRepository = InMemoryMessageRepository()
34+
35+
@classmethod
36+
def _should_migrate(cls, config: Mapping[str, Any]) -> bool:
37+
if cls.migrate_from_key in config and cls.migrate_to_key not in config:
38+
return True
39+
return False
40+
41+
@classmethod
42+
def _migrate_api_key(cls, config: Mapping[str, Any]) -> Mapping[str, Any]:
43+
config[cls.migrate_to_key] = {cls.migrate_from_key: config[cls.migrate_from_key], "auth_method": "api_key"}
44+
return config
45+
46+
@classmethod
47+
def _modify_and_save(cls, config_path: str, source: SourceAirtable, config: Mapping[str, Any]) -> Mapping[str, Any]:
48+
# modify the config
49+
migrated_config = cls._migrate_api_key(config)
50+
# save the config
51+
source.write_config(migrated_config, config_path)
52+
# return modified config
53+
return migrated_config
54+
55+
@classmethod
56+
def _emit_control_message(cls, migrated_config: Mapping[str, Any]) -> None:
57+
# add the Airbyte Control Message to message repo
58+
cls.message_repository.emit_message(create_connector_config_control_message(migrated_config))
59+
# emit the Airbyte Control Message from message queue to stdout
60+
for message in cls.message_repository._message_queue:
61+
print(orjson.dumps(AirbyteMessageSerializer.dump(message)).decode())
62+
63+
@classmethod
64+
def migrate(cls, args: List[str], source: SourceAirtable) -> None:
65+
"""
66+
This method checks the input args, should the config be migrated,
67+
transform if necessary and emit the CONTROL message.
68+
"""
69+
# get config path
70+
config_path = AirbyteEntrypoint(source).extract_config(args)
71+
# proceed only if `--config` arg is provided
72+
if config_path:
73+
# read the existing config
74+
config = source.read_config(config_path)
75+
# migration check
76+
if cls._should_migrate(config):
77+
cls._emit_control_message(
78+
cls._modify_and_save(config_path, source, config),
79+
)

0 commit comments

Comments
 (0)