tinybird 0.0.1.dev102__tar.gz → 0.0.1.dev104__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.
Potentially problematic release.
This version of tinybird might be problematic. Click here for more details.
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/PKG-INFO +2 -19
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/feedback_manager.py +6 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/sql_template.py +21 -2
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/__cli__.py +2 -2
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/cicd.py +1 -1
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/cli.py +0 -41
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/common.py +39 -5
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/create.py +2 -2
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/datafile/common.py +10 -1
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/deployment.py +45 -35
- tinybird-0.0.1.dev104/tinybird/tb/modules/infra.py +852 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/local.py +30 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/workspace.py +4 -25
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb_cli_modules/connection.py +8 -2
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird.egg-info/PKG-INFO +2 -19
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird.egg-info/requires.txt +1 -19
- tinybird-0.0.1.dev102/tinybird/tb/modules/infra.py +0 -624
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/setup.cfg +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/__cli__.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/ch_utils/constants.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/ch_utils/engine.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/check_pypi.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/client.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/config.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/connectors.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/context.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/datafile.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/datatypes.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/git_settings.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/prompts.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/sql.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/sql_template_fmt.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/sql_toolset.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/syncasync.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/cli.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/auth.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/build.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/config.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/connection.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/copy.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/datafile/build.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/datafile/build_common.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/datafile/build_datasource.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/datafile/build_pipe.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/datafile/diff.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/datafile/exceptions.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/datafile/fixture.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/datafile/format_common.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/datafile/format_datasource.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/datafile/format_pipe.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/datafile/parse_datasource.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/datafile/parse_pipe.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/datafile/pipe_checker.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/datafile/playground.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/datafile/pull.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/datasource.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/endpoint.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/exceptions.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/feedback_manager.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/fmt.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/job.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/llm.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/llm_utils.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/local_common.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/login.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/logout.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/materialization.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/mock.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/open.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/pipe.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/playground.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/project.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/regions.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/secret.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/shell.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/table.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/tag.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/telemetry.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/test.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/tinyunit/tinyunit.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/tinyunit/tinyunit_lib.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/token.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/watch.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb/modules/workspace_members.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb_cli.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb_cli_modules/auth.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb_cli_modules/branch.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb_cli_modules/cicd.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb_cli_modules/cli.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb_cli_modules/common.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb_cli_modules/config.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb_cli_modules/datasource.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb_cli_modules/exceptions.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb_cli_modules/fmt.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb_cli_modules/job.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb_cli_modules/pipe.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb_cli_modules/regions.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb_cli_modules/tag.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb_cli_modules/telemetry.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb_cli_modules/test.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb_cli_modules/workspace.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tb_cli_modules/workspace_members.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird/tornado_template.py +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird.egg-info/SOURCES.txt +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird.egg-info/dependency_links.txt +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird.egg-info/entry_points.txt +0 -0
- {tinybird-0.0.1.dev102 → tinybird-0.0.1.dev104}/tinybird.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: tinybird
|
|
3
|
-
Version: 0.0.1.
|
|
3
|
+
Version: 0.0.1.dev104
|
|
4
4
|
Summary: Tinybird Command Line Tool
|
|
5
5
|
Home-page: https://www.tinybird.co/docs/cli/introduction.html
|
|
6
6
|
Author: Tinybird
|
|
@@ -9,6 +9,7 @@ Requires-Python: >=3.9, <3.14
|
|
|
9
9
|
Description-Content-Type: text/x-rst
|
|
10
10
|
Requires-Dist: aiofiles==24.1.0
|
|
11
11
|
Requires-Dist: anthropic==0.42.0
|
|
12
|
+
Requires-Dist: boto3
|
|
12
13
|
Requires-Dist: click<8.2,>=8.1.6
|
|
13
14
|
Requires-Dist: clickhouse-toolset==0.34.dev0
|
|
14
15
|
Requires-Dist: colorama==0.4.6
|
|
@@ -32,29 +33,11 @@ Requires-Dist: wheel
|
|
|
32
33
|
Requires-Dist: packaging<24,>=23.1
|
|
33
34
|
Requires-Dist: llm>=0.19
|
|
34
35
|
Requires-Dist: thefuzz==0.22.1
|
|
35
|
-
Provides-Extra: bigquery
|
|
36
|
-
Requires-Dist: gsutil==4.58; extra == "bigquery"
|
|
37
|
-
Requires-Dist: google-api-python-client==2.0.2; extra == "bigquery"
|
|
38
|
-
Requires-Dist: google-auth==1.27.1; extra == "bigquery"
|
|
39
|
-
Requires-Dist: google-auth-httplib2==0.1.0; extra == "bigquery"
|
|
40
|
-
Requires-Dist: google-cloud-storage==2.4.0; extra == "bigquery"
|
|
41
|
-
Requires-Dist: google-cloud-bigquery==2.11.0; extra == "bigquery"
|
|
42
|
-
Provides-Extra: snowflake
|
|
43
|
-
Requires-Dist: snowflake-connector-python~=3.12.3; extra == "snowflake"
|
|
44
|
-
Requires-Dist: gsutil==4.58; extra == "snowflake"
|
|
45
|
-
Requires-Dist: google-api-python-client==2.0.2; extra == "snowflake"
|
|
46
|
-
Requires-Dist: google-auth==1.27.1; extra == "snowflake"
|
|
47
|
-
Requires-Dist: google-auth-httplib2==0.1.0; extra == "snowflake"
|
|
48
|
-
Requires-Dist: google-cloud-storage==2.4.0; extra == "snowflake"
|
|
49
|
-
Requires-Dist: oauth2client==3.0.0; extra == "snowflake"
|
|
50
|
-
Requires-Dist: chardet<4,>=3.0.2; extra == "snowflake"
|
|
51
|
-
Requires-Dist: pyOpenSSL<20.0.0,>=16.2.0; extra == "snowflake"
|
|
52
36
|
Dynamic: author
|
|
53
37
|
Dynamic: author-email
|
|
54
38
|
Dynamic: description
|
|
55
39
|
Dynamic: description-content-type
|
|
56
40
|
Dynamic: home-page
|
|
57
|
-
Dynamic: provides-extra
|
|
58
41
|
Dynamic: requires-dist
|
|
59
42
|
Dynamic: requires-python
|
|
60
43
|
Dynamic: summary
|
|
@@ -651,6 +651,12 @@ Ready? """
|
|
|
651
651
|
warning_tag_remove = prompt_message(
|
|
652
652
|
"Tag {tag_name} is used by {resources_len} resources. Do you want to remove it?"
|
|
653
653
|
)
|
|
654
|
+
warning_bigquery_connector_deprecated = warning_message(
|
|
655
|
+
"🚨🚨🚨 [DEPRECATED] BigQuery connector is deprecated. Use ingestion from GCS instead. https://www.tinybird.co/docs/get-data-in/guides/ingest-from-bigquery-using-google-cloud-storage **"
|
|
656
|
+
)
|
|
657
|
+
warning_s3_access_key_secret_deprecated = warning_message(
|
|
658
|
+
"🚨🚨🚨 [DEPRECATED] S3 (Access Key + Secret) connector is deprecated. Use S3 IAM role instead. https://www.tinybird.co/docs/get-data-in/connectors/s3 **"
|
|
659
|
+
)
|
|
654
660
|
|
|
655
661
|
info_fixtures_branch = info_message("** Data Fixtures are only pushed to Branches")
|
|
656
662
|
info_materialize_push_datasource_exists = warning_message("** Data Source {name} already exists")
|
|
@@ -2427,6 +2427,20 @@ def render_template_with_secrets(name: str, content: str, secrets: Optional[Dict
|
|
|
2427
2427
|
... )
|
|
2428
2428
|
'KAFKA_BOOTSTRAP_SERVERS localhost:9092'
|
|
2429
2429
|
|
|
2430
|
+
>>> render_template_with_secrets(
|
|
2431
|
+
... "my_kafka_connection",
|
|
2432
|
+
... "KAFKA_BOOTSTRAP_SERVERS {{ tb_secret('MISSING_SECRET', '') }}",
|
|
2433
|
+
... secrets = {}
|
|
2434
|
+
... )
|
|
2435
|
+
'KAFKA_BOOTSTRAP_SERVERS ""'
|
|
2436
|
+
|
|
2437
|
+
>>> render_template_with_secrets(
|
|
2438
|
+
... "my_kafka_connection",
|
|
2439
|
+
... "KAFKA_BOOTSTRAP_SERVERS {{ tb_secret('MISSING_SECRET', 0) }}",
|
|
2440
|
+
... secrets = {}
|
|
2441
|
+
... )
|
|
2442
|
+
'KAFKA_BOOTSTRAP_SERVERS 0'
|
|
2443
|
+
|
|
2430
2444
|
>>> render_template_with_secrets(
|
|
2431
2445
|
... "my_kafka_connection",
|
|
2432
2446
|
... "KAFKA_BOOTSTRAP_SERVERS {{ tb_secret('MISSING_SECRET') }}",
|
|
@@ -2453,8 +2467,13 @@ def render_template_with_secrets(name: str, content: str, secrets: Optional[Dict
|
|
|
2453
2467
|
SQLTemplateException: If the secret is not found and no default is provided
|
|
2454
2468
|
"""
|
|
2455
2469
|
if secret_name in secrets:
|
|
2456
|
-
|
|
2470
|
+
value = secrets[secret_name]
|
|
2471
|
+
if isinstance(value, str) and len(value) == 0:
|
|
2472
|
+
return '""'
|
|
2473
|
+
return value
|
|
2457
2474
|
elif default is not None:
|
|
2475
|
+
if isinstance(default, str) and len(default) == 0:
|
|
2476
|
+
return '""'
|
|
2458
2477
|
return default
|
|
2459
2478
|
else:
|
|
2460
2479
|
raise SQLTemplateException(
|
|
@@ -2462,7 +2481,7 @@ def render_template_with_secrets(name: str, content: str, secrets: Optional[Dict
|
|
|
2462
2481
|
)
|
|
2463
2482
|
|
|
2464
2483
|
# Create the template
|
|
2465
|
-
t = Template(content, name=name)
|
|
2484
|
+
t = Template(content, name=name, autoescape=None)
|
|
2466
2485
|
|
|
2467
2486
|
try:
|
|
2468
2487
|
# Create namespace with our tb_secret function
|
|
@@ -4,5 +4,5 @@ __description__ = 'Tinybird Command Line Tool'
|
|
|
4
4
|
__url__ = 'https://www.tinybird.co/docs/cli/introduction.html'
|
|
5
5
|
__author__ = 'Tinybird'
|
|
6
6
|
__author_email__ = 'support@tinybird.co'
|
|
7
|
-
__version__ = '0.0.1.
|
|
8
|
-
__revision__ = '
|
|
7
|
+
__version__ = '0.0.1.dev104'
|
|
8
|
+
__revision__ = 'f6c1941'
|
|
@@ -55,7 +55,7 @@ jobs:
|
|
|
55
55
|
- name: Test project
|
|
56
56
|
run: tb test run
|
|
57
57
|
- name: Deployment check
|
|
58
|
-
run: tb --cloud --host ${{! TINYBIRD_HOST }} --token ${{! TINYBIRD_TOKEN }} deploy --check
|
|
58
|
+
run: tb --cloud --host ${{! env.TINYBIRD_HOST }} --token ${{! env.TINYBIRD_TOKEN }} deploy --check
|
|
59
59
|
"""
|
|
60
60
|
|
|
61
61
|
|
|
@@ -158,47 +158,6 @@ async def pull(ctx: Context, force: bool, fmt: bool) -> None:
|
|
|
158
158
|
return await folder_pull(client, project.path, force, fmt=fmt)
|
|
159
159
|
|
|
160
160
|
|
|
161
|
-
@cli.command(hidden=True)
|
|
162
|
-
@click.option("--no-deps", is_flag=True, default=False, help="Print only data sources with no pipes using them")
|
|
163
|
-
@click.option("--match", default=None, help="Retrieve any resource matching the pattern")
|
|
164
|
-
@click.option("--pipe", default=None, help="Retrieve any resource used by pipe")
|
|
165
|
-
@click.option("--datasource", default=None, help="Retrieve resources depending on this data source")
|
|
166
|
-
@click.option(
|
|
167
|
-
"--check-for-partial-replace",
|
|
168
|
-
is_flag=True,
|
|
169
|
-
default=False,
|
|
170
|
-
help="Retrieve dependant data sources that will have their data replaced if a partial replace is executed in the data source selected",
|
|
171
|
-
)
|
|
172
|
-
@click.option("--recursive", is_flag=True, default=False, help="Calculate recursive dependencies")
|
|
173
|
-
@click.pass_context
|
|
174
|
-
@coro
|
|
175
|
-
async def dependencies(
|
|
176
|
-
ctx: Context,
|
|
177
|
-
no_deps: bool,
|
|
178
|
-
match: Optional[str],
|
|
179
|
-
pipe: Optional[str],
|
|
180
|
-
datasource: Optional[str],
|
|
181
|
-
check_for_partial_replace: bool,
|
|
182
|
-
recursive: bool,
|
|
183
|
-
) -> None:
|
|
184
|
-
"""Print all data sources dependencies."""
|
|
185
|
-
|
|
186
|
-
client = ctx.ensure_object(dict)["client"]
|
|
187
|
-
|
|
188
|
-
response = await client.datasource_dependencies(
|
|
189
|
-
no_deps, match, pipe, datasource, check_for_partial_replace, recursive
|
|
190
|
-
)
|
|
191
|
-
for ds in response["dependencies"]:
|
|
192
|
-
click.echo(FeedbackManager.info_dependency_list(dependency=ds))
|
|
193
|
-
for pipe in response["dependencies"][ds]:
|
|
194
|
-
click.echo(FeedbackManager.info_dependency_list_item(dependency=pipe))
|
|
195
|
-
if "incompatible_datasources" in response and len(response["incompatible_datasources"]):
|
|
196
|
-
click.echo(FeedbackManager.info_no_compatible_dependencies_found())
|
|
197
|
-
for ds in response["incompatible_datasources"]:
|
|
198
|
-
click.echo(FeedbackManager.info_dependency_list(dependency=ds))
|
|
199
|
-
raise CLIException(FeedbackManager.error_partial_replace_cant_be_executed(datasource=datasource))
|
|
200
|
-
|
|
201
|
-
|
|
202
161
|
@cli.command(
|
|
203
162
|
name="diff",
|
|
204
163
|
short_help="Diff local datafiles to the corresponding remote files in the workspace. Only diffs VERSION and SCHEMA for .datasource files.",
|
|
@@ -81,8 +81,6 @@ SUPPORTED_FORMATS = ["csv", "ndjson", "json", "parquet"]
|
|
|
81
81
|
OLDEST_ROLLBACK = "oldest_rollback"
|
|
82
82
|
MAIN_BRANCH = "main"
|
|
83
83
|
|
|
84
|
-
CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"])
|
|
85
|
-
|
|
86
84
|
|
|
87
85
|
def obfuscate_token(value: Optional[str]) -> Optional[str]:
|
|
88
86
|
if not value:
|
|
@@ -1984,12 +1982,12 @@ async def send_batch_events(
|
|
|
1984
1982
|
click.echo(FeedbackManager.highlight(message=f"» {rows} rows x {cols} cols in {elapsed_time:.1f}s"))
|
|
1985
1983
|
|
|
1986
1984
|
|
|
1987
|
-
async def get_organizations_by_user(config: CLIConfig, user_token: str) -> List[Dict[str,
|
|
1985
|
+
async def get_organizations_by_user(config: CLIConfig, user_token: Optional[str] = None) -> List[Dict[str, str]]:
|
|
1988
1986
|
"""Fetches all organizations by user using the provided user token"""
|
|
1989
1987
|
organizations = []
|
|
1990
1988
|
|
|
1991
1989
|
try:
|
|
1992
|
-
user_client = config.get_client(token=user_token)
|
|
1990
|
+
user_client = config.get_client(token=user_token) if user_token else config.get_user_client()
|
|
1993
1991
|
user_workspaces = await user_client.user_workspaces_with_organization(version="v1")
|
|
1994
1992
|
admin_org_id = user_workspaces.get("organization_id")
|
|
1995
1993
|
seen_org_ids = set()
|
|
@@ -2089,7 +2087,7 @@ async def ask_for_organization_name(config: CLIConfig) -> str:
|
|
|
2089
2087
|
user_email.split("@")[0] if user_email else None
|
|
2090
2088
|
) # Example: "jane.doe@gmail.com" -> "jane.doe"
|
|
2091
2089
|
return click.prompt(
|
|
2092
|
-
"\nYou need to create an organization to continue
|
|
2090
|
+
"\nYou need to create an organization to continue.\nEnter organization name",
|
|
2093
2091
|
hide_input=False,
|
|
2094
2092
|
show_default=True,
|
|
2095
2093
|
default=default_organization_name,
|
|
@@ -2166,3 +2164,39 @@ def get_ui_url(api_host: str) -> str:
|
|
|
2166
2164
|
return f"https://cloud.tinybird.co/{cloud}/{region}"
|
|
2167
2165
|
|
|
2168
2166
|
return api_host
|
|
2167
|
+
|
|
2168
|
+
|
|
2169
|
+
async def ask_for_organization(
|
|
2170
|
+
organizations: Optional[List[Dict[str, Any]]],
|
|
2171
|
+
organization_id: Optional[str] = None,
|
|
2172
|
+
user_token: Optional[str] = None,
|
|
2173
|
+
) -> Tuple[Optional[str], Optional[str]]:
|
|
2174
|
+
config = CLIConfig.get_project_config()
|
|
2175
|
+
user_email = config.get_user_email()
|
|
2176
|
+
|
|
2177
|
+
if organization_id:
|
|
2178
|
+
if organizations and len(organizations) > 0:
|
|
2179
|
+
organization = next((org for org in organizations if org.get("id") == organization_id), None)
|
|
2180
|
+
if not organization:
|
|
2181
|
+
raise CLIException(FeedbackManager.error_organization_not_found(organization_id=organization_id))
|
|
2182
|
+
organization_name = organization.get("name")
|
|
2183
|
+
return organization_id, organization_name
|
|
2184
|
+
|
|
2185
|
+
if organizations is None or len(organizations) == 0:
|
|
2186
|
+
organization_name = await ask_for_organization_name(config)
|
|
2187
|
+
user_token = await get_user_token(config, user_token)
|
|
2188
|
+
organization = await create_organization_and_add_workspaces(config, organization_name, user_token)
|
|
2189
|
+
organization_id = organization.get("id")
|
|
2190
|
+
else:
|
|
2191
|
+
if len(organizations) == 1:
|
|
2192
|
+
organization_name = organizations[0]["name"]
|
|
2193
|
+
organization_id = organizations[0]["id"]
|
|
2194
|
+
else:
|
|
2195
|
+
sorted_organizations = sort_organizations_by_user(organizations, user_email=user_email)
|
|
2196
|
+
current_organization = await ask_for_organization_interactively(sorted_organizations)
|
|
2197
|
+
if current_organization:
|
|
2198
|
+
organization_id = current_organization.get("id")
|
|
2199
|
+
organization_name = current_organization.get("name")
|
|
2200
|
+
else:
|
|
2201
|
+
return None, None
|
|
2202
|
+
return organization_id, organization_name
|
|
@@ -299,9 +299,9 @@ def init_git(folder: str):
|
|
|
299
299
|
if gitignore_file.exists():
|
|
300
300
|
content = gitignore_file.read_text()
|
|
301
301
|
if ".tinyb" not in content:
|
|
302
|
-
gitignore_file.write_text(content + "\n.tinyb\n")
|
|
302
|
+
gitignore_file.write_text(content + "\n.tinyb\n.terraform\n")
|
|
303
303
|
else:
|
|
304
|
-
gitignore_file.write_text(".tinyb\n")
|
|
304
|
+
gitignore_file.write_text(".tinyb\n.terraform\n")
|
|
305
305
|
|
|
306
306
|
click.echo(FeedbackManager.info_file_created(file=".gitignore"))
|
|
307
307
|
except Exception as e:
|
|
@@ -1241,6 +1241,13 @@ def parse(
|
|
|
1241
1241
|
|
|
1242
1242
|
return _f
|
|
1243
1243
|
|
|
1244
|
+
def kafka_key_avro_deserialization(*args: str, **kwargs: Any):
|
|
1245
|
+
raise DatafileSyntaxError(
|
|
1246
|
+
f'{kwargs["cmd"].upper()} has been deprecated. Use "KAFKA_KEY_FORMAT avro" instead',
|
|
1247
|
+
lineno=kwargs["lineno"],
|
|
1248
|
+
pos=1,
|
|
1249
|
+
)
|
|
1250
|
+
|
|
1244
1251
|
@deprecated
|
|
1245
1252
|
def sources(x: str, **kwargs: Any) -> None:
|
|
1246
1253
|
pass # Deprecated
|
|
@@ -1459,11 +1466,13 @@ def parse(
|
|
|
1459
1466
|
"kafka_store_raw_value": assign_var("kafka_store_raw_value"),
|
|
1460
1467
|
"kafka_store_headers": assign_var("kafka_store_headers"),
|
|
1461
1468
|
"kafka_store_binary_headers": assign_var("kafka_store_binary_headers"),
|
|
1462
|
-
"kafka_key_avro_deserialization":
|
|
1469
|
+
"kafka_key_avro_deserialization": kafka_key_avro_deserialization,
|
|
1463
1470
|
"kafka_ssl_ca_pem": assign_var("kafka_ssl_ca_pem"),
|
|
1464
1471
|
"kafka_security_protocol": assign_var("kafka_security_protocol"),
|
|
1465
1472
|
"kafka_sasl_mechanism": assign_var("kafka_sasl_mechanism"),
|
|
1466
1473
|
"import_service": assign_var("import_service"),
|
|
1474
|
+
"s3_region": assign_var("s3_region"),
|
|
1475
|
+
"s3_arn": assign_var("s3_arn"),
|
|
1467
1476
|
"import_connection_name": assign_var("import_connection_name"),
|
|
1468
1477
|
"import_schedule": assign_var("import_schedule"),
|
|
1469
1478
|
"import_strategy": assign_var("import_strategy"),
|
|
@@ -19,6 +19,7 @@ from tinybird.tb.modules.project import Project
|
|
|
19
19
|
def api_fetch(url: str, headers: dict) -> dict:
|
|
20
20
|
r = requests.get(url, headers=headers)
|
|
21
21
|
if r.status_code == 200:
|
|
22
|
+
logging.debug(json.dumps(r.json(), indent=2))
|
|
22
23
|
return r.json()
|
|
23
24
|
# Try to parse and print the error from the response
|
|
24
25
|
try:
|
|
@@ -32,13 +33,33 @@ def api_fetch(url: str, headers: dict) -> dict:
|
|
|
32
33
|
sys.exit(1)
|
|
33
34
|
|
|
34
35
|
|
|
36
|
+
def api_post(
|
|
37
|
+
url: str,
|
|
38
|
+
headers: dict,
|
|
39
|
+
files: Optional[list] = None,
|
|
40
|
+
params: Optional[dict] = None,
|
|
41
|
+
) -> dict:
|
|
42
|
+
r = requests.post(url, headers=headers, files=files, params=params)
|
|
43
|
+
if r.status_code == 200:
|
|
44
|
+
logging.debug(json.dumps(r.json(), indent=2))
|
|
45
|
+
return r.json()
|
|
46
|
+
# Try to parse and print the error from the response
|
|
47
|
+
try:
|
|
48
|
+
result = r.json()
|
|
49
|
+
logging.debug(json.dumps(result, indent=2))
|
|
50
|
+
error = result.get("error")
|
|
51
|
+
click.echo(FeedbackManager.error(message=f"Error: {error}"))
|
|
52
|
+
sys.exit(1)
|
|
53
|
+
except Exception:
|
|
54
|
+
click.echo(FeedbackManager.error(message="Error parsing response from API"))
|
|
55
|
+
sys.exit(1)
|
|
56
|
+
|
|
57
|
+
|
|
35
58
|
# TODO(eclbg): This logic should be in the server, and there should be a dedicated endpoint for promoting a deployment
|
|
36
59
|
# potato
|
|
37
60
|
def promote_deployment(host: Optional[str], headers: dict, wait: bool) -> None:
|
|
38
61
|
TINYBIRD_API_URL = f"{host}/v1/deployments"
|
|
39
|
-
|
|
40
|
-
result = r.json()
|
|
41
|
-
logging.debug(json.dumps(result, indent=2))
|
|
62
|
+
result = api_fetch(TINYBIRD_API_URL, headers)
|
|
42
63
|
|
|
43
64
|
deployments = result.get("deployments")
|
|
44
65
|
if not deployments:
|
|
@@ -64,12 +85,7 @@ def promote_deployment(host: Optional[str], headers: dict, wait: bool) -> None:
|
|
|
64
85
|
click.echo(FeedbackManager.success(message="Setting candidate deployment as live"))
|
|
65
86
|
|
|
66
87
|
TINYBIRD_API_URL = f"{host}/v1/deployments/{candidate_deployment.get('id')}/set-live"
|
|
67
|
-
|
|
68
|
-
result = r.json()
|
|
69
|
-
logging.debug(json.dumps(result, indent=2))
|
|
70
|
-
if result.get("error"):
|
|
71
|
-
click.echo(FeedbackManager.error(message=result.get("error")))
|
|
72
|
-
sys.exit(1)
|
|
88
|
+
result = api_post(TINYBIRD_API_URL, headers=headers)
|
|
73
89
|
|
|
74
90
|
click.echo(FeedbackManager.success(message="Removing old deployment"))
|
|
75
91
|
|
|
@@ -86,9 +102,7 @@ def promote_deployment(host: Optional[str], headers: dict, wait: bool) -> None:
|
|
|
86
102
|
if wait:
|
|
87
103
|
while True:
|
|
88
104
|
TINYBIRD_API_URL = f"{host}/v1/deployments/{last_deployment.get('id')}"
|
|
89
|
-
|
|
90
|
-
result = r.json()
|
|
91
|
-
logging.debug(json.dumps(result, indent=2))
|
|
105
|
+
result = api_fetch(TINYBIRD_API_URL, headers=headers)
|
|
92
106
|
|
|
93
107
|
last_deployment = result.get("deployment")
|
|
94
108
|
if last_deployment.get("status") == "deleted":
|
|
@@ -102,9 +116,7 @@ def promote_deployment(host: Optional[str], headers: dict, wait: bool) -> None:
|
|
|
102
116
|
# deployment
|
|
103
117
|
def rollback_deployment(host: Optional[str], headers: dict, wait: bool) -> None:
|
|
104
118
|
TINYBIRD_API_URL = f"{host}/v1/deployments"
|
|
105
|
-
|
|
106
|
-
result = r.json()
|
|
107
|
-
logging.debug(json.dumps(result, indent=2))
|
|
119
|
+
result = api_fetch(TINYBIRD_API_URL, headers=headers)
|
|
108
120
|
|
|
109
121
|
deployments = result.get("deployments")
|
|
110
122
|
if not deployments:
|
|
@@ -130,12 +142,7 @@ def rollback_deployment(host: Optional[str], headers: dict, wait: bool) -> None:
|
|
|
130
142
|
click.echo(FeedbackManager.success(message="Promoting previous deployment"))
|
|
131
143
|
|
|
132
144
|
TINYBIRD_API_URL = f"{host}/v1/deployments/{previous_deployment.get('id')}/set-live"
|
|
133
|
-
|
|
134
|
-
result = r.json()
|
|
135
|
-
logging.debug(json.dumps(result, indent=2))
|
|
136
|
-
if result.get("error"):
|
|
137
|
-
click.echo(FeedbackManager.error(message=result.get("error")))
|
|
138
|
-
sys.exit(1)
|
|
145
|
+
result = api_post(TINYBIRD_API_URL, headers=headers)
|
|
139
146
|
|
|
140
147
|
click.echo(FeedbackManager.success(message="Removing current deployment"))
|
|
141
148
|
|
|
@@ -152,9 +159,7 @@ def rollback_deployment(host: Optional[str], headers: dict, wait: bool) -> None:
|
|
|
152
159
|
if wait:
|
|
153
160
|
while True:
|
|
154
161
|
TINYBIRD_API_URL = f"{host}/v1/deployments/{current_deployment.get('id')}"
|
|
155
|
-
|
|
156
|
-
result = r.json()
|
|
157
|
-
logging.debug(json.dumps(result, indent=2))
|
|
162
|
+
result = api_fetch(TINYBIRD_API_URL, headers)
|
|
158
163
|
|
|
159
164
|
current_deployment = result.get("deployment")
|
|
160
165
|
if current_deployment.get("status") == "deleted":
|
|
@@ -219,7 +224,6 @@ def deployment_ls(ctx: click.Context) -> None:
|
|
|
219
224
|
url = f"{client.host}/v1/deployments"
|
|
220
225
|
|
|
221
226
|
result = api_fetch(url, HEADERS)
|
|
222
|
-
logging.debug(json.dumps(result, indent=2))
|
|
223
227
|
|
|
224
228
|
status_map = {"data_ready": "Ready", "failed": "Failed"}
|
|
225
229
|
columns = ["ID", "Status", "Created at", "Live"]
|
|
@@ -354,13 +358,13 @@ def create_deployment(
|
|
|
354
358
|
params["check"] = "true"
|
|
355
359
|
if allow_destructive_operations:
|
|
356
360
|
params["allow_destructive_operations"] = "true"
|
|
357
|
-
|
|
358
|
-
result =
|
|
359
|
-
logging.debug(json.dumps(result, indent=2))
|
|
361
|
+
|
|
362
|
+
result = api_post(TINYBIRD_API_URL, headers=HEADERS, files=files, params=params)
|
|
360
363
|
|
|
361
364
|
print_changes(result, project)
|
|
362
365
|
|
|
363
|
-
|
|
366
|
+
deployment = result.get("deployment", {})
|
|
367
|
+
feedback = deployment.get("feedback", [])
|
|
364
368
|
for f in feedback:
|
|
365
369
|
if f.get("level", "").upper() == "ERROR":
|
|
366
370
|
feedback_func = FeedbackManager.error
|
|
@@ -372,7 +376,7 @@ def create_deployment(
|
|
|
372
376
|
resource_bit = f"{resource}: " if resource else ""
|
|
373
377
|
click.echo(feedback_func(message=f"{feedback_icon}{f.get('level')}: {resource_bit}{f.get('message')}"))
|
|
374
378
|
|
|
375
|
-
deploy_errors =
|
|
379
|
+
deploy_errors = deployment.get("errors")
|
|
376
380
|
for deploy_error in deploy_errors:
|
|
377
381
|
if deploy_error.get("filename", None):
|
|
378
382
|
click.echo(
|
|
@@ -380,19 +384,21 @@ def create_deployment(
|
|
|
380
384
|
)
|
|
381
385
|
else:
|
|
382
386
|
click.echo(FeedbackManager.error(message=f"{deploy_error.get('error')}"))
|
|
387
|
+
click.echo() # For spacing
|
|
383
388
|
|
|
384
389
|
status = result.get("result")
|
|
385
390
|
if check:
|
|
386
391
|
if status == "success":
|
|
387
392
|
click.echo(FeedbackManager.success(message="\n✓ Deployment is valid"))
|
|
388
393
|
sys.exit(0)
|
|
394
|
+
elif status == "no_changes":
|
|
395
|
+
sys.exit(0)
|
|
389
396
|
|
|
390
397
|
click.echo(FeedbackManager.error(message="\n✗ Deployment is not valid"))
|
|
391
398
|
sys.exit(1)
|
|
392
399
|
|
|
393
400
|
status = result.get("result")
|
|
394
401
|
if status == "success":
|
|
395
|
-
deployment = result.get("deployment", {})
|
|
396
402
|
# TODO: This is a hack to show the url in the case of region is public. The URL should be returned by the API
|
|
397
403
|
if client.host == "https://api.europe-west2.gcp.tinybird.co":
|
|
398
404
|
click.echo(
|
|
@@ -406,10 +412,14 @@ def create_deployment(
|
|
|
406
412
|
click.echo(FeedbackManager.info(message="\n✓ Deployment submitted successfully"))
|
|
407
413
|
else:
|
|
408
414
|
click.echo(FeedbackManager.success(message="\n✓ Deployment submitted successfully"))
|
|
415
|
+
elif status == "no_changes":
|
|
416
|
+
click.echo(FeedbackManager.highlight(message="Not deploying. No changes."))
|
|
417
|
+
sys.exit(0)
|
|
409
418
|
elif status == "failed":
|
|
410
419
|
click.echo(FeedbackManager.error(message="Deployment failed"))
|
|
420
|
+
sys.exit(1)
|
|
411
421
|
else:
|
|
412
|
-
click.echo(FeedbackManager.error(message=f"Unknown
|
|
422
|
+
click.echo(FeedbackManager.error(message=f"Unknown deployment result {status}"))
|
|
413
423
|
except Exception as e:
|
|
414
424
|
click.echo(FeedbackManager.error_exception(error=e))
|
|
415
425
|
finally:
|
|
@@ -463,7 +473,7 @@ def print_changes(result: dict, project: Project) -> None:
|
|
|
463
473
|
resources.append(["new", p, project.get_resource_path(p, "pipe")])
|
|
464
474
|
|
|
465
475
|
for dc in deployment.get("new_data_connector_names", []):
|
|
466
|
-
resources.append(["new", dc, project.get_resource_path(dc, "
|
|
476
|
+
resources.append(["new", dc, project.get_resource_path(dc, "connection")])
|
|
467
477
|
|
|
468
478
|
for ds in deployment.get("changed_datasource_names", []):
|
|
469
479
|
resources.append(["modified", ds, project.get_resource_path(ds, "datasource")])
|
|
@@ -472,7 +482,7 @@ def print_changes(result: dict, project: Project) -> None:
|
|
|
472
482
|
resources.append(["modified", p, project.get_resource_path(p, "pipe")])
|
|
473
483
|
|
|
474
484
|
for dc in deployment.get("changed_data_connector_names", []):
|
|
475
|
-
resources.append(["modified", dc, project.get_resource_path(dc, "
|
|
485
|
+
resources.append(["modified", dc, project.get_resource_path(dc, "connection")])
|
|
476
486
|
|
|
477
487
|
for ds in deployment.get("deleted_datasource_names", []):
|
|
478
488
|
resources.append(["deleted", ds, project.get_resource_path(ds, "datasource")])
|
|
@@ -481,7 +491,7 @@ def print_changes(result: dict, project: Project) -> None:
|
|
|
481
491
|
resources.append(["deleted", p, project.get_resource_path(p, "pipe")])
|
|
482
492
|
|
|
483
493
|
for dc in deployment.get("deleted_data_connector_names", []):
|
|
484
|
-
resources.append(["deleted", dc, project.get_resource_path(dc, "
|
|
494
|
+
resources.append(["deleted", dc, project.get_resource_path(dc, "connection")])
|
|
485
495
|
|
|
486
496
|
for token_change in deployment.get("token_changes", []):
|
|
487
497
|
token_name = token_change.get("token_name")
|