tinybird-cli 3.2.0__tar.gz → 3.6.1.dev9__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 (48) hide show
  1. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/PKG-INFO +106 -7
  2. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/__cli__.py +3 -3
  3. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/ch_utils/engine.py +52 -2
  4. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/client.py +15 -0
  5. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/config.py +1 -0
  6. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/connector_settings.py +89 -3
  7. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/context.py +1 -0
  8. tinybird-cli-3.6.1.dev9/tinybird/data_connectors/credentials.py +31 -0
  9. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/datafile.py +685 -271
  10. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/feedback_manager.py +87 -18
  11. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/git_settings.py +13 -1
  12. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/sql.py +91 -3
  13. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/sql_template.py +50 -0
  14. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/sql_template_fmt.py +22 -1
  15. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/tb_cli_modules/auth.py +1 -1
  16. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/tb_cli_modules/branch.py +28 -1
  17. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/tb_cli_modules/cicd.py +66 -30
  18. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/tb_cli_modules/cli.py +71 -24
  19. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/tb_cli_modules/common.py +40 -22
  20. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/tb_cli_modules/connection.py +146 -2
  21. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/tb_cli_modules/datasource.py +20 -2
  22. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/tb_cli_modules/pipe.py +43 -8
  23. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/tb_cli_modules/test.py +19 -3
  24. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/tb_cli_modules/workspace_members.py +3 -3
  25. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/tornado_template.py +1 -0
  26. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird_cli.egg-info/PKG-INFO +106 -7
  27. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird_cli.egg-info/SOURCES.txt +1 -0
  28. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird_cli.egg-info/requires.txt +1 -1
  29. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird_cli.egg-info/top_level.txt +1 -1
  30. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/setup.cfg +0 -0
  31. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/ch_utils/constants.py +0 -0
  32. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/check_pypi.py +0 -0
  33. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/connectors.py +0 -0
  34. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/datatypes.py +0 -0
  35. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/sql_toolset.py +0 -0
  36. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/syncasync.py +0 -0
  37. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/tb_cli.py +0 -0
  38. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/tb_cli_modules/config.py +0 -0
  39. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/tb_cli_modules/exceptions.py +0 -0
  40. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/tb_cli_modules/job.py +0 -0
  41. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/tb_cli_modules/regions.py +0 -0
  42. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/tb_cli_modules/telemetry.py +0 -0
  43. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
  44. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
  45. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/tb_cli_modules/token.py +0 -0
  46. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird/tb_cli_modules/workspace.py +0 -0
  47. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird_cli.egg-info/dependency_links.txt +0 -0
  48. {tinybird-cli-3.2.0 → tinybird-cli-3.6.1.dev9}/tinybird_cli.egg-info/entry_points.txt +0 -0
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tinybird-cli
3
- Version: 3.2.0
3
+ Version: 3.6.1.dev9
4
4
  Summary: Tinybird Command Line Tool
5
- Home-page: https://docs.tinybird.co/cli.html
5
+ Home-page: https://www.tinybird.co/docs/cli/introduction.html
6
6
  Author: Tinybird
7
7
  Author-email: support@tinybird.co
8
8
  Requires-Python: >=3.8, <3.12
@@ -11,7 +11,7 @@ Provides-Extra: bigquery
11
11
  Provides-Extra: snowflake
12
12
 
13
13
  Tinybird CLI
14
- ============
14
+ =============
15
15
 
16
16
  The Tinybird command-line tool allows you to use all the Tinybird functionality directly from the command line. Additionally, it includes several functions to create and manage data projects easily.
17
17
 
@@ -19,16 +19,115 @@ Changelog
19
19
 
20
20
  ---------
21
21
 
22
+ 3.6.1.dev9
23
+ ************
24
+
25
+ - `Fixed` Added correct URL for checking available regions
26
+
27
+
28
+ 3.6.1.dev8
29
+ ************
30
+
31
+ - `Fixed` Report better error message on `tb diff` when two Datafiles have the same name
32
+
33
+ 3.6.1.dev7
34
+ ************
35
+
36
+ - `Fixed` `tb deploy` supports deployment when a `.incl` file is removed
37
+
38
+ 3.6.1.dev6
39
+ ************
40
+
41
+ - `Fixed` Some issues when using `--fmt: off` with `CASE` in the sql
42
+
43
+ 3.6.1.dev5
44
+ ************
45
+
46
+ - `Fixed` Avoid `tb fmt` to error if there's a `CASE` in the sql
47
+
48
+ 3.6.1.dev4
49
+ ************
50
+
51
+ - `Fixed` regression tests query when filtering by specific parameter
52
+
53
+ 3.6.1.dev3
54
+ ************
55
+
56
+ - `Changed` behavior when running `tb deploy` on a branch to push the connection settings to the backend. This change is the backend that decides what to do.
57
+
58
+ 3.6.1.dev2
59
+ ************
60
+
61
+ - `Changed` fixed major version of tinybird-cli to lower than 4 when using `tb init --git`
62
+
63
+ 3.6.0
64
+ ************
65
+
66
+ - `Added` Add new envvar `TB_INCL_RELATIVE_PATH` in .tinyenv to look for Datafiles out of the Data Project directory
67
+ - `Changed` On-demand Sink run checks the pipe type instead of checking the workspace connectors
68
+
69
+ 3.5.0
70
+ ************
71
+
72
+ - `Added` Token management in Copy pipes datafiles
73
+ - `Added` Better error report on `tb push` when trying to push a pipe with bad templating
74
+ - `Added` credential validation for S3 connections
75
+ - `Added` `tb connection create` now supports `s3_iamrole` as service type
76
+ - `Changed` error message when trying to modify a datasource without bumping the major semver version to add a link to the documentation.
77
+ - `Changed` GH workflow files and secret includes the workspace name when generated from the UI and CLI
78
+ - `Changed` rename `INDICES` to `INDEXES`
79
+ - `Changed` Save git commit to workspace on `tb push --only-changes`
80
+ - `Fixed` Fix error message when deleting an `.incl` file with the git workflow
81
+ - `Fixed` support `tb deploy --dry-run`
82
+
83
+
84
+ 3.4.0
85
+ ************
86
+
87
+ - `Added` Support `tb deploy` .datasource with `INDEXES`
88
+ - `Added` Support `tb push` .datasource with `INDEXES`
89
+ - `Added` Support `tb deploy` in a post release of a .datasource with `INDEXES`
90
+ - `Added` Check backfill on preview is required when `tb deploy` modified datasources. Disable check with `TB_CHECK_BACKFILL_REQUIRED=0`.
91
+ - `Changed` Allow spaces when managing multiple Workspace members
92
+ - `Changed` `tb deploy` to not allow pushing materialized views with datasource definition in the same datafile. We are blocking this as has unsupported behavior and it misleading and less flexible than having 2 files one for the datasource and one for the materialized view.
93
+ - `Changed` `tb deploy` to deploy the datasources from top to bottom to make sure that if we modified the column in some datasource in the top. It will be deployed before the datasources that depend on it.
94
+ - `Changed` Post-release required when deploying changes that include changing a Copy Pipe.
95
+ - `Changed` script `exec_test.sh` from `tb init --git` to run retries to avoid flakiness in tests
96
+ - `Changed` Update `tb release rm --oldest-rollback` to use new API
97
+ - `Fixed` Post-release recommended instead of required when deploying changes that include changing a Copy Pipe. Displays a warning when other number of the semver is increased.
98
+ - `Fixed` Fixed bug when a Data Source was created using an INDEX
99
+ - `Fixed` Avoid None git diff change type
100
+ - `Fixed` `tb deploy` to deploy the endpoints in the correct order when there are endpoints depending on other endpoints.
101
+ - `Fixed` `tb push` pipe with multiple tokens
102
+ - `Fixed` `IMPORT` and `ENGINE` changes were not detected `tb deploy`
103
+ - `Removed` part of the code supporting python 3.6 as we stopped giving support 18 month ago
104
+
105
+
106
+ 3.3.0
107
+ ************
108
+
109
+ - `Added` Show warning when doing data or pipe operations directly against Live.
110
+ - `Added` `bi_stats`, `bi_stats_rt` and `endpoint_errors` to the list of service data sources that the CLI ignore when looking for dependencies of pipes being pushed.
111
+ - `Added` S3 Iam Role connection creation
112
+ - `Added` Connector credential validation
113
+ - `Added` Data quality tests inside a `skip_in_branch` folder inside the `tests` folder are skipped when running on a branch. Use this to skip tests in the CI piipeline that should only run with production data.
114
+ - `Changed` Stop creating endpoints folder on tb init
115
+ - `Changed` Small refactoring of the connector credentials
116
+ - `Fixed` Progress bar in `tb init --git`.
117
+ - `Fixed` Don't do diff when there are no modified resources on `tb deploy`.
118
+ - `Fixed` Upgrade GitPython dependency to 3.1.32. That version fixes the security vulnerability `CVE-2022-24439 <https://github.com/advisories/GHSA-hcpj-qp55-gfph>`
119
+ - `Fixed` Homepage URL in PyPI
120
+
22
121
  3.2.0
23
122
  ************
24
123
 
25
124
  - `Changed` `tb init --git` uses v3.1.0 of the CI templates (See release notes: https://github.com/tinybirdco/ci/releases/tag/v3.1.0)
26
- - `Changed` Allow alter datasource with jsonpaths to add DEFAULTS if the datasource already have any (See release notes: https://github.com/tinybirdco/ci/releases/tag/v3.1.0)
125
+ - `Changed` Allow alter data source with JSON paths to add DEFAULTS if the data source already has any (See release notes: https://github.com/tinybirdco/ci/releases/tag/v3.1.0)
27
126
 
28
127
  3.1.0
29
128
  ************
30
129
 
31
- - `Added` `tb init --cicd` to generate CI/CD files not only when using `--git`. Combine with `--force` for overwrite
130
+ - `Added` `tb init --cicd` to generate CI/CD files not only when using `--git`. Combine with `--force` to overwrite
32
131
  - `Added` Ignore format changes on `tb deploy` by default
33
132
  - `Changed` `tb init --git` and `tb release generate` include `set -euxo pipefail` in the generated bash scripts
34
133
  - `Changed` `tb init --git` uses github.com/tinybirdco/ci => v3.0.0
@@ -36,7 +135,7 @@ Changelog
36
135
  - `Changed` `tb release promote` automatically deletes de oldest rollback Release if `export TB_FORCE_REMOVE_OLDEST_ROLLBACK=1`
37
136
  - `Changed` option `--node` in `tb pipe populate` to required as it is already mandatory to specify the node to populate. Now, it will provide an error message if the `--node` option is not provided.
38
137
  - `Changed` Better error report on `tb fmt --diff`. Use it in CI to standardize Datafile formatting
39
- - `Changed` `tb init --git` generates a requirements.txt file to install the latest tinybird-cli release from pypi
138
+ - `Changed` `tb init --git` generates a requirements.txt file to install the latest tinybird-cli release from PyPI
40
139
  - `Changed` `tb deploy` shows an example when failing because of a missing `--semver` argument
41
140
  - `Fixed` When parsing the response of a CSV `tb sql` command, the CLI was interpreting the result as an error in some cases.
42
141
 
@@ -45,7 +144,7 @@ Changelog
45
144
 
46
145
  Major version updated to 3.0.0 due to the change in the logic of `tb deploy`. From this version on, `tb deploy` promotes Releases to Live or Preview based on the semver version.
47
146
 
48
- See `our Version Control guides <https://versions.tinybird.co/docs/version-control/deployment-strategies.html#semver-deployment-behaviour>`_ for more details about our semver deployment behaviour.
147
+ See `our Version Control guides <https://www.tinybird.co/docs/version-control/deployment-strategies.html#semver-deployment-behaviour>`_ for more details about our semver deployment behaviour.
49
148
 
50
149
  - `Added` `syncing` status to git remote settings
51
150
  - `Added` `tb release rm --oldest-rollback --force --yes` deletes the oldest rollback Release by creation date
@@ -1,8 +1,8 @@
1
1
 
2
2
  __name__ = 'tinybird-cli'
3
3
  __description__ = 'Tinybird Command Line Tool'
4
- __url__ = 'https://docs.tinybird.co/cli.html'
4
+ __url__ = 'https://www.tinybird.co/docs/cli/introduction.html'
5
5
  __author__ = 'Tinybird'
6
6
  __author_email__ = 'support@tinybird.co'
7
- __version__ = '3.2.0'
8
- __revision__ = '3067b41'
7
+ __version__ = '3.6.1.dev9'
8
+ __revision__ = 'ff22a5b'
@@ -1,9 +1,10 @@
1
1
  import logging
2
2
  import re
3
3
  from collections import defaultdict
4
+ from dataclasses import asdict
4
5
  from typing import Any, Callable, Dict, Iterable, List, Optional
5
6
 
6
- from ..sql import col_name, engine_replicated_to_local, parse_table_structure
7
+ from ..sql import TableIndex, col_name, engine_replicated_to_local, parse_indexes_structure, parse_table_structure
7
8
 
8
9
  DEFAULT_EMPTY_PARAMETERS = ["ttl", "partition_key", "sorting_key"]
9
10
  DEFAULT_JOIN_EMPTY_PARAMETERS = ["join_strictness", "join_type", "key_columns"]
@@ -31,7 +32,20 @@ class TableDetails:
31
32
  >>> ed.to_datafile()
32
33
  ''
33
34
 
35
+ >>> ed = TableDetails({ "engine_full": "MergeTree() PARTITION BY toYear(timestamp) ORDER BY (timestamp, cityHash64(location)) SAMPLE BY cityHash64(location) SETTINGS index_granularity = 32, index_granularity_bytes = 2048", "engine": "MergeTree", "partition_key": "toYear(timestamp)", "sorting_key": "timestamp, cityHash64(location)", "primary_key": "timestamp, cityHash64(location)", "sampling_key": "cityHash64(location)", "settings": "index_granularity = 32, index_granularity_bytes = 2048", "ttl": None })
36
+ >>> ed.diff_ttl("toDate(timestamp) + toIntervalDay(1)")
37
+ True
34
38
  >>> ed = TableDetails({ "engine_full": "MergeTree() PARTITION BY toYear(timestamp) ORDER BY (timestamp, cityHash64(location)) SAMPLE BY cityHash64(location) SETTINGS index_granularity = 32, index_granularity_bytes = 2048 TTL toDate(timestamp) + INTERVAL 1 DAY", "engine": "MergeTree", "partition_key": "toYear(timestamp)", "sorting_key": "timestamp, cityHash64(location)", "primary_key": "timestamp, cityHash64(location)", "sampling_key": "cityHash64(location)", "settings": "index_granularity = 32, index_granularity_bytes = 2048", "ttl": "toDate(timestamp) + INTERVAL 1 DAY" })
39
+ >>> ed.diff_ttl("toDate(timestamp) + toIntervalDay(1)")
40
+ False
41
+ >>> ed.diff_ttl("toDate(timestamp) + toIntervalDay(2)")
42
+ True
43
+ >>> ed.diff_ttl("toDate(timestamp) + INTERVAL DAY 2")
44
+ True
45
+ >>> ed.diff_ttl("toDate(timestamp) + INTERVAL 1 DAY")
46
+ False
47
+ >>> ed.diff_ttl("")
48
+ True
35
49
  >>> ed.engine_full
36
50
  'MergeTree() PARTITION BY toYear(timestamp) ORDER BY (timestamp, cityHash64(location)) SAMPLE BY cityHash64(location) SETTINGS index_granularity = 32, index_granularity_bytes = 2048 TTL toDate(timestamp) + INTERVAL 1 DAY'
37
51
  >>> ed.engine
@@ -131,6 +145,16 @@ class TableDetails:
131
145
  return is_aggregating or is_replacing or is_collapsing
132
146
  return False
133
147
 
148
+ def diff_ttl(self, new_ttl: str) -> bool:
149
+ try:
150
+ from tinybird.sql_toolset import format_sql
151
+
152
+ current_ttl = format_sql(f"select {self.ttl}")[7:]
153
+ new_ttl = format_sql(f"select {new_ttl}")[7:]
154
+ return current_ttl != new_ttl
155
+ except Exception:
156
+ return self.ttl != new_ttl
157
+
134
158
  @property
135
159
  def partition_key(self) -> Optional[str]:
136
160
  return self.details.get("partition_key", None)
@@ -204,6 +228,10 @@ class TableDetails:
204
228
  "row_count": self.details.get("total_rows", None),
205
229
  }
206
230
 
231
+ @property
232
+ def indexes(self) -> List[TableIndex]:
233
+ return _parse_indexes(str(self.details.get("create_table_query", "")))
234
+
207
235
  def to_json(self, exclude: Optional[List[str]] = None, include_empty_details: bool = False):
208
236
  # name, database are not exported since they are not part of the engine
209
237
  d: Dict[str, Any] = {
@@ -234,6 +262,8 @@ class TableDetails:
234
262
  d["version"] = self.version
235
263
  if self.ttl:
236
264
  d["ttl"] = self.ttl.strip()
265
+ if self.indexes:
266
+ d["indexes"] = [asdict(index) for index in self.indexes]
237
267
 
238
268
  if self.engine_full:
239
269
  engine_params = engine_params_from_engine_full(self.engine_full)
@@ -253,7 +283,9 @@ class TableDetails:
253
283
  return d
254
284
 
255
285
  def to_datafile(self, include_empty_details: bool = False) -> str:
256
- d: Dict[str, Any] = self.to_json(exclude=["engine", "engine_full"], include_empty_details=include_empty_details)
286
+ d: Dict[str, Any] = self.to_json(
287
+ exclude=["engine", "engine_full", "indexes"], include_empty_details=include_empty_details
288
+ )
257
289
  engine: str = self.engine
258
290
 
259
291
  datafile: str = ""
@@ -774,3 +806,21 @@ def ttl_condition_from_engine_full(engine_full: Optional[str]) -> Optional[str]:
774
806
  except Exception as e:
775
807
  logging.error(str(e))
776
808
  return None
809
+
810
+
811
+ def _parse_indexes(create_table_query_expr: str) -> List[TableIndex]:
812
+ if create_table_query_expr == "":
813
+ return []
814
+ try:
815
+ from tinybird.sql_toolset import format_sql
816
+
817
+ indexes = [
818
+ line.strip()
819
+ for line in format_sql(create_table_query_expr).splitlines()
820
+ if line.strip().startswith("INDEX")
821
+ ]
822
+ except ModuleNotFoundError:
823
+ # this is not needed from CLI
824
+ return []
825
+
826
+ return parse_indexes_structure(indexes)
@@ -306,6 +306,7 @@ class TinyB(object):
306
306
  description: Optional[str] = None,
307
307
  ttl: Optional[str] = None,
308
308
  dry_run: bool = False,
309
+ indexes: Optional[str] = None,
309
310
  ):
310
311
  params = {"dry": "true" if dry_run else "false"}
311
312
  if new_schema:
@@ -314,6 +315,8 @@ class TinyB(object):
314
315
  params.update({"description": description})
315
316
  if ttl:
316
317
  params.update({"ttl": ttl})
318
+ if indexes:
319
+ params.update({"indexes": indexes})
317
320
  res = await self._req(f"/v0/datasources/{ds_name}/alter", method="POST", data=params)
318
321
 
319
322
  if "Error" in res:
@@ -991,6 +994,12 @@ class TinyB(object):
991
994
  response = await self._req(f"/v0/connectors/snowflake/warehouses?{urlencode(params)}", method="POST", data="")
992
995
  return response["warehouses"]
993
996
 
997
+ async def get_s3_trust_policy(self) -> Dict[str, Any]:
998
+ return await self._req("/v0/integrations/s3/policies/trust-policy")
999
+
1000
+ async def get_s3_access_policy(self) -> Dict[str, Any]:
1001
+ return await self._req("/v0/integrations/s3/policies/access-policy")
1002
+
994
1003
  async def sql_get_format(self, sql: str, with_clickhouse_format: bool = False) -> str:
995
1004
  try:
996
1005
  if with_clickhouse_format:
@@ -1099,6 +1108,12 @@ class TinyB(object):
1099
1108
  params["confirmation"] = confirmation
1100
1109
  return await self._req(f"/v0/workspaces/{workspace_id}/releases/{semver}?{urlencode(params)}", method="DELETE")
1101
1110
 
1111
+ async def release_oldest_rollback(
1112
+ self,
1113
+ workspace_id: str,
1114
+ ):
1115
+ return await self._req(f"/v0/workspaces/{workspace_id}/releases/oldest-rollback", method="GET")
1116
+
1102
1117
  async def token_list(self, match: Optional[str] = None):
1103
1118
  tokens = await self.tokens()
1104
1119
  return [token for token in tokens if (not match or token["name"].find(match) != -1) and "token" in token]
@@ -20,6 +20,7 @@ VERSION = f"{__cli__.__version__} (rev {__revision__})"
20
20
  DEFAULT_UI_HOST = "https://ui.tinybird.co"
21
21
  SUPPORTED_CONNECTORS = ["bigquery", "snowflake"]
22
22
  PROJECT_PATHS = ["datasources", "datasources/fixtures", "endpoints", "pipes", "tests", "scripts", "deploy"]
23
+ DEPRECATED_PROJECT_PATHS = ["endpoints"]
23
24
  MIN_WORKSPACE_ID_LENGTH = 36
24
25
 
25
26
 
@@ -1,10 +1,19 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from enum import Enum
4
- from typing import List, Optional
4
+ from typing import List, Optional, Union
5
5
 
6
6
  from pydantic import BaseModel
7
7
 
8
+ from tinybird.data_connectors.credentials import (
9
+ GCSConnectorCredentials,
10
+ GCSServiceAccountCredentials,
11
+ IAMRoleAWSCredentials,
12
+ S3ConnectorCredentials,
13
+ )
14
+
15
+ GCS_BASE_URL = "https://storage.googleapis.com"
16
+
8
17
 
9
18
  class DataConnectorType(str, Enum):
10
19
  KAFKA = "kafka"
@@ -13,6 +22,7 @@ class DataConnectorType(str, Enum):
13
22
  BIGQUERY = "bigquery"
14
23
  GCLOUD_STORAGE = "gcs"
15
24
  GCLOUD_STORAGE_HMAC = "gcs_hmac"
25
+ GCLOUD_STORAGE_SA = "gcs_service_account"
16
26
  AMAZON_S3 = "s3"
17
27
  AMAZON_S3_IAMROLE = "s3_iamrole"
18
28
 
@@ -24,7 +34,11 @@ DataConnectors = DataConnectorType # this is just to make picking happy
24
34
 
25
35
 
26
36
  class DataConnectorSetting(BaseModel):
27
- ...
37
+ def get_region(self) -> str:
38
+ return "unknown"
39
+
40
+ def get_provider_name(self) -> str:
41
+ return "unknown"
28
42
 
29
43
 
30
44
  class KafkaConnectorSetting(DataConnectorSetting):
@@ -42,12 +56,42 @@ class S3ConnectorSetting(DataConnectorSetting):
42
56
  s3_access_key_id: str
43
57
  s3_secret_access_key: str
44
58
  s3_region: str
59
+ endpoint_url: Optional[str] = None
60
+
61
+ @property
62
+ def credentials(self) -> S3ConnectorCredentials:
63
+ return S3ConnectorCredentials(
64
+ access_key_id=self.s3_access_key_id,
65
+ secret_access_key=self.s3_secret_access_key,
66
+ region=self.s3_region,
67
+ )
68
+
69
+ def get_provider_name(self) -> str:
70
+ return DataConnectorType.AMAZON_S3
71
+
72
+ def get_region(self) -> str:
73
+ return self.s3_region
45
74
 
46
75
 
47
76
  class S3IAMConnectorSetting(DataConnectorSetting):
48
77
  s3_iamrole_arn: str
49
78
  s3_iamrole_region: str
50
- s3_iamrole_external_id: Optional[str] = None
79
+ s3_iamrole_external_id: str
80
+ endpoint_url: Optional[str] = None
81
+
82
+ @property
83
+ def credentials(self) -> IAMRoleAWSCredentials:
84
+ return IAMRoleAWSCredentials(
85
+ role_arn=self.s3_iamrole_arn,
86
+ external_id=self.s3_iamrole_external_id,
87
+ region=self.s3_iamrole_region,
88
+ )
89
+
90
+ def get_provider_name(self) -> str:
91
+ return DataConnectorType.AMAZON_S3
92
+
93
+ def get_region(self) -> str:
94
+ return self.s3_iamrole_region
51
95
 
52
96
 
53
97
  class SnowflakeConnectorSetting(DataConnectorSetting):
@@ -69,9 +113,32 @@ class BigQueryConnectorSetting(DataConnectorSetting):
69
113
  account: Optional[str] = None
70
114
 
71
115
 
116
+ class GCSServiceAccountConnectorSetting(DataConnectorSetting):
117
+ account_email: str
118
+ endpoint_url: str = GCS_BASE_URL
119
+
120
+ @property
121
+ def credentials(self) -> GCSServiceAccountCredentials:
122
+ return GCSServiceAccountCredentials(account_email=self.account_email)
123
+
124
+ def get_provider_name(self) -> str:
125
+ return DataConnectorType.GCLOUD_STORAGE
126
+
127
+
72
128
  class GCSHmacConnectorSetting(DataConnectorSetting):
73
129
  gcs_hmac_access_id: str
74
130
  gcs_hmac_secret: str
131
+ endpoint_url: str = GCS_BASE_URL
132
+
133
+ @property
134
+ def credentials(self) -> GCSConnectorCredentials:
135
+ return GCSConnectorCredentials(
136
+ access_key_id=self.gcs_hmac_access_id,
137
+ secret_access_key=self.gcs_hmac_secret,
138
+ )
139
+
140
+ def get_provider_name(self) -> str:
141
+ return DataConnectorType.GCLOUD_STORAGE
75
142
 
76
143
 
77
144
  class GCSConnectorSetting(DataConnectorSetting):
@@ -90,10 +157,15 @@ DATA_CONNECTOR_SETTINGS: dict[DataConnectors, type[DataConnectorSetting]] = {
90
157
  DataConnectors.BIGQUERY: BigQueryConnectorSetting,
91
158
  DataConnectors.GCLOUD_STORAGE: GCSConnectorSetting,
92
159
  DataConnectors.GCLOUD_STORAGE_HMAC: GCSHmacConnectorSetting,
160
+ DataConnectors.GCLOUD_STORAGE_SA: GCSServiceAccountConnectorSetting,
93
161
  DataConnectors.AMAZON_S3: S3ConnectorSetting,
94
162
  DataConnectors.AMAZON_S3_IAMROLE: S3IAMConnectorSetting,
95
163
  }
96
164
 
165
+ SinkConnectorSettings = Union[
166
+ S3ConnectorSetting, S3IAMConnectorSetting, GCSHmacConnectorSetting, GCSServiceAccountConnectorSetting
167
+ ]
168
+
97
169
 
98
170
  class DataLinkerSettings:
99
171
  kafka = [
@@ -137,6 +209,13 @@ class DataSinkSettings:
137
209
  "format",
138
210
  "compression",
139
211
  ]
212
+ gcs_service_account = [
213
+ "bucket_path",
214
+ "file_template",
215
+ "partition_node",
216
+ "format",
217
+ "compression",
218
+ ]
140
219
 
141
220
 
142
221
  class DataSensitiveSettings:
@@ -151,3 +230,10 @@ class DataSensitiveSettings:
151
230
  gcs_hmac: List[str] = ["gcs_hmac_secret"]
152
231
  s3: List[str] = ["s3_secret_access_key"]
153
232
  s3_iamrole: List[str] = ["s3_iamrole_arn"]
233
+
234
+
235
+ CLI_EXCLUDED_SETTINGS = {
236
+ "gcs_hmac": ["endpoint_url"],
237
+ "s3": ["endpoint_url"],
238
+ "s3_iamrole": ["endpoint_url"],
239
+ }
@@ -6,6 +6,7 @@ table_id: ContextVar[str] = ContextVar("table_id")
6
6
  hfi_frequency: ContextVar[float] = ContextVar("hfi_frequency")
7
7
  hfi_frequency_gatherer: ContextVar[float] = ContextVar("hfi_frequency_gatherer")
8
8
  hfi_use_gatherer: ContextVar[bool] = ContextVar("hfi_use_gatherer")
9
+ use_gatherer: ContextVar[bool] = ContextVar("use_gatherer")
9
10
  disable_template_security_validation: ContextVar[bool] = ContextVar("disable_template_security_validation")
10
11
  origin: ContextVar[str] = ContextVar("origin")
11
12
  request_id: ContextVar[str] = ContextVar("request_id")
@@ -0,0 +1,31 @@
1
+ import abc
2
+ import dataclasses
3
+
4
+
5
+ class ConnectorCredentials(abc.ABC):
6
+ pass
7
+
8
+
9
+ @dataclasses.dataclass(frozen=True)
10
+ class S3ConnectorCredentials(ConnectorCredentials):
11
+ access_key_id: str
12
+ secret_access_key: str
13
+ region: str
14
+
15
+
16
+ @dataclasses.dataclass(frozen=True)
17
+ class IAMRoleAWSCredentials(ConnectorCredentials):
18
+ role_arn: str
19
+ external_id: str
20
+ region: str
21
+
22
+
23
+ @dataclasses.dataclass(frozen=True)
24
+ class GCSConnectorCredentials(ConnectorCredentials):
25
+ access_key_id: str
26
+ secret_access_key: str
27
+
28
+
29
+ @dataclasses.dataclass(frozen=True)
30
+ class GCSServiceAccountCredentials(ConnectorCredentials):
31
+ account_email: str