tinybird 0.0.1.dev117__py3-none-any.whl → 0.0.1.dev118__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.
Potentially problematic release.
This version of tinybird might be problematic. Click here for more details.
- tinybird/config.py +6 -2
- tinybird/tb/__cli__.py +2 -2
- tinybird/tb/modules/common.py +105 -37
- tinybird/tb/modules/connection.py +44 -12
- tinybird/tb/modules/create.py +9 -8
- tinybird/tb/modules/deployment.py +19 -15
- tinybird/tb/modules/feedback_manager.py +92 -5
- {tinybird-0.0.1.dev117.dist-info → tinybird-0.0.1.dev118.dist-info}/METADATA +1 -1
- {tinybird-0.0.1.dev117.dist-info → tinybird-0.0.1.dev118.dist-info}/RECORD +12 -12
- {tinybird-0.0.1.dev117.dist-info → tinybird-0.0.1.dev118.dist-info}/WHEEL +0 -0
- {tinybird-0.0.1.dev117.dist-info → tinybird-0.0.1.dev118.dist-info}/entry_points.txt +0 -0
- {tinybird-0.0.1.dev117.dist-info → tinybird-0.0.1.dev118.dist-info}/top_level.txt +0 -0
tinybird/config.py
CHANGED
|
@@ -124,8 +124,12 @@ def get_display_host(ui_host: str):
|
|
|
124
124
|
return LEGACY_HOSTS.get(ui_host, ui_host)
|
|
125
125
|
|
|
126
126
|
|
|
127
|
-
def get_display_cloud_host(
|
|
128
|
-
|
|
127
|
+
def get_display_cloud_host(api_host: str) -> str:
|
|
128
|
+
is_local = "localhost" in api_host
|
|
129
|
+
if is_local:
|
|
130
|
+
port = api_host.split(":")[-1]
|
|
131
|
+
return f"http://cloud.tinybird.co/local/{port}"
|
|
132
|
+
return CLOUD_HOSTS.get(api_host, api_host)
|
|
129
133
|
|
|
130
134
|
|
|
131
135
|
class FeatureFlags:
|
tinybird/tb/__cli__.py
CHANGED
|
@@ -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.dev118'
|
|
8
|
+
__revision__ = '5932fa5'
|
tinybird/tb/modules/common.py
CHANGED
|
@@ -1754,27 +1754,26 @@ async def remove_release(
|
|
|
1754
1754
|
async def run_aws_iamrole_connection_flow(
|
|
1755
1755
|
client: TinyB,
|
|
1756
1756
|
service: str,
|
|
1757
|
-
|
|
1758
|
-
):
|
|
1757
|
+
environment: str,
|
|
1758
|
+
) -> Tuple[str, str, str]:
|
|
1759
1759
|
if service == DataConnectorType.AMAZON_DYNAMODB:
|
|
1760
|
-
raise NotImplementedError("DynamoDB is not supported
|
|
1760
|
+
raise NotImplementedError("DynamoDB is not supported")
|
|
1761
1761
|
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1762
|
+
bucket_name = click.prompt(
|
|
1763
|
+
"📦 Bucket name (specific name recommended, use '*' for unrestricted access in IAM policy)",
|
|
1764
|
+
prompt_suffix="\n> ",
|
|
1765
|
+
)
|
|
1766
|
+
validate_string_connector_param("Bucket", bucket_name)
|
|
1765
1767
|
|
|
1766
|
-
|
|
1767
|
-
validate_string_connector_param("Region",
|
|
1768
|
+
region = click.prompt("🌐 Region (the region where the bucket is located, e.g. 'us-east-1')", prompt_suffix="\n> ")
|
|
1769
|
+
validate_string_connector_param("Region", region)
|
|
1768
1770
|
|
|
1769
|
-
access_policy, trust_policy,
|
|
1770
|
-
access_policy = access_policy.replace("<bucket>",
|
|
1771
|
+
access_policy, trust_policy, _ = await get_aws_iamrole_policies(client, service=service, policy="read")
|
|
1772
|
+
access_policy = access_policy.replace("<bucket>", bucket_name)
|
|
1771
1773
|
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
prompt_suffix="Press y to continue:",
|
|
1776
|
-
):
|
|
1777
|
-
sys.exit(1)
|
|
1774
|
+
click.echo(FeedbackManager.prompt_s3_iamrole_connection_login_aws())
|
|
1775
|
+
click.echo(FeedbackManager.click_enter_to_continue())
|
|
1776
|
+
input()
|
|
1778
1777
|
|
|
1779
1778
|
access_policy_copied = True
|
|
1780
1779
|
try:
|
|
@@ -1782,16 +1781,58 @@ async def run_aws_iamrole_connection_flow(
|
|
|
1782
1781
|
except Exception:
|
|
1783
1782
|
access_policy_copied = False
|
|
1784
1783
|
|
|
1785
|
-
|
|
1784
|
+
# Display message and wait for user to press Enter
|
|
1785
|
+
click.echo(
|
|
1786
|
+
FeedbackManager.prompt_s3_iamrole_connection_policy(
|
|
1787
|
+
access_policy=access_policy, aws_region=region, bucket=bucket_name
|
|
1788
|
+
)
|
|
1789
|
+
if access_policy_copied
|
|
1790
|
+
else FeedbackManager.prompt_s3_iamrole_connection_policy_not_copied(
|
|
1791
|
+
access_policy=access_policy, aws_region=region, bucket=bucket_name
|
|
1792
|
+
)
|
|
1793
|
+
)
|
|
1794
|
+
click.echo(FeedbackManager.click_enter_to_continue())
|
|
1795
|
+
input()
|
|
1796
|
+
|
|
1797
|
+
trust_policy_copied = True
|
|
1798
|
+
try:
|
|
1799
|
+
pyperclip.copy(trust_policy)
|
|
1800
|
+
except Exception:
|
|
1801
|
+
trust_policy_copied = False
|
|
1802
|
+
|
|
1803
|
+
role_arn = click.prompt(
|
|
1786
1804
|
(
|
|
1787
|
-
FeedbackManager.
|
|
1788
|
-
|
|
1789
|
-
|
|
1805
|
+
FeedbackManager.prompt_s3_iamrole_connection_role(
|
|
1806
|
+
trust_policy=trust_policy,
|
|
1807
|
+
aws_region=region,
|
|
1808
|
+
bucket=bucket_name,
|
|
1809
|
+
environment=environment.upper(),
|
|
1810
|
+
step="3",
|
|
1811
|
+
)
|
|
1812
|
+
if trust_policy_copied
|
|
1813
|
+
else FeedbackManager.prompt_s3_iamrole_connection_role_not_copied(
|
|
1814
|
+
trust_policy=trust_policy,
|
|
1815
|
+
aws_region=region,
|
|
1816
|
+
bucket=bucket_name,
|
|
1817
|
+
environment=environment.upper(),
|
|
1818
|
+
step="3",
|
|
1819
|
+
)
|
|
1790
1820
|
),
|
|
1791
1821
|
show_default=False,
|
|
1792
|
-
|
|
1793
|
-
)
|
|
1794
|
-
|
|
1822
|
+
)
|
|
1823
|
+
validate_string_connector_param("Role ARN", role_arn)
|
|
1824
|
+
|
|
1825
|
+
return role_arn, region, bucket_name
|
|
1826
|
+
|
|
1827
|
+
|
|
1828
|
+
async def production_aws_iamrole_only(
|
|
1829
|
+
prod_client: TinyB,
|
|
1830
|
+
service: str,
|
|
1831
|
+
region: str,
|
|
1832
|
+
bucket_name: str,
|
|
1833
|
+
environment: str,
|
|
1834
|
+
) -> Tuple[str, str, str]:
|
|
1835
|
+
_, trust_policy, external_id = await get_aws_iamrole_policies(prod_client, service=service, policy="read")
|
|
1795
1836
|
|
|
1796
1837
|
trust_policy_copied = True
|
|
1797
1838
|
try:
|
|
@@ -1799,21 +1840,29 @@ async def run_aws_iamrole_connection_flow(
|
|
|
1799
1840
|
except Exception:
|
|
1800
1841
|
trust_policy_copied = False
|
|
1801
1842
|
|
|
1802
|
-
|
|
1843
|
+
role_arn = click.prompt(
|
|
1803
1844
|
(
|
|
1804
|
-
FeedbackManager.prompt_s3_iamrole_connection_role(
|
|
1845
|
+
FeedbackManager.prompt_s3_iamrole_connection_role(
|
|
1846
|
+
trust_policy=trust_policy,
|
|
1847
|
+
aws_region=region,
|
|
1848
|
+
bucket=bucket_name,
|
|
1849
|
+
environment=environment.upper(),
|
|
1850
|
+
step="4",
|
|
1851
|
+
)
|
|
1805
1852
|
if trust_policy_copied
|
|
1806
|
-
else FeedbackManager.prompt_s3_iamrole_connection_role_not_copied(
|
|
1853
|
+
else FeedbackManager.prompt_s3_iamrole_connection_role_not_copied(
|
|
1854
|
+
trust_policy=trust_policy,
|
|
1855
|
+
aws_region=region,
|
|
1856
|
+
bucket=bucket_name,
|
|
1857
|
+
environment=environment.upper(),
|
|
1858
|
+
step="4",
|
|
1859
|
+
)
|
|
1807
1860
|
),
|
|
1808
1861
|
show_default=False,
|
|
1809
|
-
|
|
1810
|
-
):
|
|
1811
|
-
sys.exit(1)
|
|
1812
|
-
|
|
1813
|
-
role_arn = click.prompt("Enter the ARN of the role you just created")
|
|
1862
|
+
)
|
|
1814
1863
|
validate_string_connector_param("Role ARN", role_arn)
|
|
1815
1864
|
|
|
1816
|
-
return role_arn,
|
|
1865
|
+
return role_arn, region, external_id
|
|
1817
1866
|
|
|
1818
1867
|
|
|
1819
1868
|
async def get_aws_iamrole_policies(client: TinyB, service: str, policy: str = "write"):
|
|
@@ -1846,16 +1895,35 @@ async def get_aws_iamrole_policies(client: TinyB, service: str, policy: str = "w
|
|
|
1846
1895
|
return json.dumps(access_policy, indent=4), json.dumps(trust_policy, indent=4), external_id
|
|
1847
1896
|
|
|
1848
1897
|
|
|
1849
|
-
|
|
1898
|
+
def get_s3_connection_name(project_folder: str) -> str:
|
|
1850
1899
|
connection_name = None
|
|
1900
|
+
valid_pattern = r"^[a-zA-Z][a-zA-Z0-9_]*$"
|
|
1901
|
+
|
|
1851
1902
|
while not connection_name:
|
|
1852
|
-
connection_name = click.prompt(
|
|
1903
|
+
connection_name = click.prompt(
|
|
1904
|
+
"🔗 Enter a name for your new Tinybird S3 connection (use alphanumeric characters, and underscores)",
|
|
1905
|
+
prompt_suffix="\n> ",
|
|
1906
|
+
show_default=True,
|
|
1907
|
+
)
|
|
1853
1908
|
assert isinstance(connection_name, str)
|
|
1854
1909
|
|
|
1855
|
-
|
|
1856
|
-
|
|
1910
|
+
# Validate against invalid characters
|
|
1911
|
+
if not re.match(valid_pattern, connection_name):
|
|
1912
|
+
if not connection_name[0].isalpha():
|
|
1913
|
+
click.echo("Error: Connection name must start with a letter.")
|
|
1914
|
+
else:
|
|
1915
|
+
click.echo("Error: Connection name can only contain letters, numbers, and underscores.")
|
|
1857
1916
|
connection_name = None
|
|
1858
|
-
|
|
1917
|
+
continue
|
|
1918
|
+
|
|
1919
|
+
# Check for existing connection with the same name
|
|
1920
|
+
project_folder_path = Path(project_folder)
|
|
1921
|
+
connection_files = list(project_folder_path.glob("*.connection"))
|
|
1922
|
+
for conn_file in connection_files:
|
|
1923
|
+
if conn_file.stem == connection_name:
|
|
1924
|
+
click.echo(FeedbackManager.error_connection_file_already_exists(name=f"{connection_name}.connection"))
|
|
1925
|
+
connection_name = None
|
|
1926
|
+
break
|
|
1859
1927
|
return connection_name
|
|
1860
1928
|
|
|
1861
1929
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
# - If it makes sense and only when strictly necessary, you can create utility functions in this file.
|
|
4
4
|
# - But please, **do not** interleave utility functions and command definitions.
|
|
5
5
|
|
|
6
|
+
import uuid
|
|
6
7
|
from typing import Any, Dict, List, Optional
|
|
7
8
|
|
|
8
9
|
import click
|
|
@@ -15,10 +16,11 @@ from tinybird.tb.modules.common import (
|
|
|
15
16
|
_get_setting_value,
|
|
16
17
|
coro,
|
|
17
18
|
echo_safe_humanfriendly_tables_format_smart_table,
|
|
19
|
+
get_s3_connection_name,
|
|
20
|
+
production_aws_iamrole_only,
|
|
18
21
|
run_aws_iamrole_connection_flow,
|
|
19
|
-
validate_aws_iamrole_connection_name,
|
|
20
22
|
)
|
|
21
|
-
from tinybird.tb.modules.create import
|
|
23
|
+
from tinybird.tb.modules.create import generate_aws_iamrole_connection_file_with_secret
|
|
22
24
|
from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
23
25
|
from tinybird.tb.modules.project import Project
|
|
24
26
|
|
|
@@ -148,20 +150,50 @@ async def connection_create_s3(ctx: Context) -> None:
|
|
|
148
150
|
project: Project = ctx.ensure_object(dict)["project"]
|
|
149
151
|
obj: Dict[str, Any] = ctx.ensure_object(dict)
|
|
150
152
|
client: TinyB = obj["client"]
|
|
153
|
+
|
|
151
154
|
service = DataConnectorType.AMAZON_S3
|
|
152
|
-
|
|
153
|
-
|
|
155
|
+
click.echo(FeedbackManager.prompt_s3_connection_header())
|
|
156
|
+
connection_name = get_s3_connection_name(project.folder)
|
|
157
|
+
role_arn, region, bucket_name = await run_aws_iamrole_connection_flow(
|
|
154
158
|
client,
|
|
155
159
|
service=service,
|
|
156
|
-
|
|
160
|
+
environment=obj["env"],
|
|
161
|
+
)
|
|
162
|
+
unique_suffix = uuid.uuid4().hex[:8] # Use first 8 chars of a UUID for brevity
|
|
163
|
+
secret_name = f"s3_role_arn_{connection_name}_{unique_suffix}"
|
|
164
|
+
await client.create_secret(name=secret_name, value=role_arn)
|
|
165
|
+
|
|
166
|
+
create_in_cloud = (
|
|
167
|
+
click.confirm(FeedbackManager.prompt_s3_iamrole_success_cloud(), default=True)
|
|
168
|
+
if obj["env"] == "local"
|
|
169
|
+
else False
|
|
157
170
|
)
|
|
158
171
|
|
|
159
|
-
|
|
160
|
-
|
|
172
|
+
if create_in_cloud:
|
|
173
|
+
prod_config = obj["config"]
|
|
174
|
+
host = prod_config["host"]
|
|
175
|
+
token = prod_config["token"]
|
|
176
|
+
prod_client = TinyB(
|
|
177
|
+
token=token,
|
|
178
|
+
host=host,
|
|
179
|
+
staging=False,
|
|
180
|
+
)
|
|
181
|
+
prod_role_arn, _, _ = await production_aws_iamrole_only(
|
|
182
|
+
prod_client, service=service, region=region, bucket_name=bucket_name, environment="cloud"
|
|
183
|
+
)
|
|
184
|
+
await prod_client.create_secret(name=secret_name, value=prod_role_arn)
|
|
185
|
+
|
|
186
|
+
connection_file_path = await generate_aws_iamrole_connection_file_with_secret(
|
|
187
|
+
name=connection_name,
|
|
188
|
+
service=service,
|
|
189
|
+
role_arn_secret_name=secret_name,
|
|
190
|
+
region=region,
|
|
191
|
+
folder=project.folder,
|
|
161
192
|
)
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
)
|
|
193
|
+
|
|
194
|
+
click.echo(
|
|
195
|
+
FeedbackManager.prompt_s3_iamrole_success(
|
|
196
|
+
connection_name=connection_name,
|
|
197
|
+
connection_path=str(connection_file_path),
|
|
167
198
|
)
|
|
199
|
+
)
|
tinybird/tb/modules/create.py
CHANGED
|
@@ -362,26 +362,27 @@ def generate_pipe_file(name: str, content: str, folder: str) -> Path:
|
|
|
362
362
|
return f.relative_to(folder)
|
|
363
363
|
|
|
364
364
|
|
|
365
|
-
def generate_connection_file(name: str, content: str, folder: str) -> Path:
|
|
365
|
+
def generate_connection_file(name: str, content: str, folder: str, skip_feedback: bool = False) -> Path:
|
|
366
366
|
base = Path(folder) / "connections"
|
|
367
367
|
if not base.exists():
|
|
368
368
|
base.mkdir()
|
|
369
369
|
f = base / (f"{name}.connection")
|
|
370
370
|
with open(f"{f}", "w") as file:
|
|
371
371
|
file.write(content)
|
|
372
|
-
|
|
372
|
+
if not skip_feedback:
|
|
373
|
+
click.echo(FeedbackManager.info_file_created(file=f.relative_to(folder)))
|
|
373
374
|
return f.relative_to(folder)
|
|
374
375
|
|
|
375
376
|
|
|
376
|
-
async def
|
|
377
|
-
name: str, service: str,
|
|
378
|
-
) ->
|
|
377
|
+
async def generate_aws_iamrole_connection_file_with_secret(
|
|
378
|
+
name: str, service: str, role_arn_secret_name: str, region: str, folder: str
|
|
379
|
+
) -> Path:
|
|
379
380
|
content = f"""TYPE {service}
|
|
380
|
-
|
|
381
|
-
S3_ARN {role_arn}
|
|
381
|
+
S3_ARN {{{{ tb_secret("{role_arn_secret_name}") }}}}
|
|
382
382
|
S3_REGION {region}
|
|
383
383
|
"""
|
|
384
|
-
generate_connection_file(name, content, folder)
|
|
384
|
+
file_path = generate_connection_file(name, content, folder, skip_feedback=True)
|
|
385
|
+
return file_path
|
|
385
386
|
|
|
386
387
|
|
|
387
388
|
def create_rules(folder: str, source: str, agent: str):
|
|
@@ -10,7 +10,7 @@ import click
|
|
|
10
10
|
import requests
|
|
11
11
|
|
|
12
12
|
from tinybird.tb.modules.cli import cli
|
|
13
|
-
from tinybird.tb.modules.common import echo_safe_humanfriendly_tables_format_smart_table
|
|
13
|
+
from tinybird.tb.modules.common import echo_safe_humanfriendly_tables_format_smart_table, get_display_cloud_host
|
|
14
14
|
from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
15
15
|
from tinybird.tb.modules.project import Project
|
|
16
16
|
|
|
@@ -214,8 +214,14 @@ def deployment_create(
|
|
|
214
214
|
|
|
215
215
|
|
|
216
216
|
@deployment_group.command(name="ls")
|
|
217
|
+
@click.option(
|
|
218
|
+
"--include-deleted",
|
|
219
|
+
is_flag=True,
|
|
220
|
+
default=False,
|
|
221
|
+
help="Include deleted deployments. Disabled by default.",
|
|
222
|
+
)
|
|
217
223
|
@click.pass_context
|
|
218
|
-
def deployment_ls(ctx: click.Context) -> None:
|
|
224
|
+
def deployment_ls(ctx: click.Context, include_deleted: bool) -> None:
|
|
219
225
|
"""
|
|
220
226
|
List all the deployments you have in the project.
|
|
221
227
|
"""
|
|
@@ -224,11 +230,12 @@ def deployment_ls(ctx: click.Context) -> None:
|
|
|
224
230
|
TINYBIRD_API_KEY = client.token
|
|
225
231
|
HEADERS = {"Authorization": f"Bearer {TINYBIRD_API_KEY}"}
|
|
226
232
|
url = f"{client.host}/v1/deployments"
|
|
233
|
+
if include_deleted:
|
|
234
|
+
url += "?include_deleted=true"
|
|
227
235
|
|
|
228
236
|
result = api_fetch(url, HEADERS)
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
columns = ["ID", "Status", "Created at", "Live"]
|
|
237
|
+
status_map = {"data_ready": "Staging", "failed": "Failed", "deleted": "Deleted"}
|
|
238
|
+
columns = ["ID", "Status", "Created at"]
|
|
232
239
|
table = []
|
|
233
240
|
for deployment in result.get("deployments", []):
|
|
234
241
|
if deployment.get("id") == "0":
|
|
@@ -237,12 +244,12 @@ def deployment_ls(ctx: click.Context) -> None:
|
|
|
237
244
|
table.append(
|
|
238
245
|
[
|
|
239
246
|
deployment.get("id"),
|
|
240
|
-
status_map.get(deployment.get("status"
|
|
247
|
+
"Live" if deployment.get("live") else status_map.get(deployment.get("status", "In progress")),
|
|
241
248
|
datetime.fromisoformat(deployment.get("created_at")).strftime("%Y-%m-%d %H:%M:%S"),
|
|
242
|
-
deployment.get("live"),
|
|
243
249
|
]
|
|
244
250
|
)
|
|
245
251
|
|
|
252
|
+
table.reverse()
|
|
246
253
|
echo_safe_humanfriendly_tables_format_smart_table(table, column_names=columns)
|
|
247
254
|
|
|
248
255
|
|
|
@@ -401,14 +408,11 @@ def create_deployment(
|
|
|
401
408
|
|
|
402
409
|
status = result.get("result")
|
|
403
410
|
if status == "success":
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
message=f"https://cloud.tinybird.co/gcp/europe-west2/{config.get('name')}/deployments/{deployment.get('id')}"
|
|
410
|
-
)
|
|
411
|
-
)
|
|
411
|
+
host = get_display_cloud_host(client.host)
|
|
412
|
+
click.echo(
|
|
413
|
+
FeedbackManager.gray(message="Deployment URL: ")
|
|
414
|
+
+ FeedbackManager.info(message=f"{host}/{config.get('name')}/deployments/{deployment.get('id')}")
|
|
415
|
+
)
|
|
412
416
|
|
|
413
417
|
if wait:
|
|
414
418
|
click.echo(FeedbackManager.info(message="\n✓ Deployment submitted successfully"))
|
|
@@ -496,19 +496,106 @@ class FeedbackManager:
|
|
|
496
496
|
Ready? """
|
|
497
497
|
)
|
|
498
498
|
|
|
499
|
-
|
|
499
|
+
# S3 IAM Role Connection Messages
|
|
500
|
+
prompt_s3_connection_header = info_highlight_message("""
|
|
501
|
+
──────────────────────────────────────────────────────────────
|
|
502
|
+
S3 CONNECTION SETUP
|
|
503
|
+
──────────────────────────────────────────────────────────────""")
|
|
504
|
+
|
|
505
|
+
prompt_s3_iamrole_connection_login_aws = prompt_message("""
|
|
506
|
+
──────────────────────────────────────────────────────────────
|
|
507
|
+
STEP 1: AWS AUTHENTICATION
|
|
508
|
+
──────────────────────────────────────────────────────────────
|
|
509
|
+
|
|
510
|
+
Please log into your \033]8;;https://console.aws.amazon.com/\033\\AWS Console\033]8;;\033\\. We'll guide you through creating the necessary permissions.
|
|
511
|
+
|
|
512
|
+
You'll be creating a single IAM Policy and Roles (you will need one per environment, Local and Cloud) to access your S3 data. Using IAM Roles improves security by providing temporary credentials and following least privilege principles.""")
|
|
513
|
+
|
|
500
514
|
prompt_s3_iamrole_connection_policy = prompt_message(
|
|
501
|
-
"""
|
|
515
|
+
"""
|
|
516
|
+
──────────────────────────────────────────────────────────────
|
|
517
|
+
STEP 2: CREATE IAM POLICY
|
|
518
|
+
──────────────────────────────────────────────────────────────
|
|
519
|
+
|
|
520
|
+
1. Go to \033]8;;https://console.aws.amazon.com/iamv2/home?region={aws_region}#/policies/create\033\\AWS IAM > Create Policy\033]8;;\033\\
|
|
521
|
+
2. Select the JSON tab
|
|
522
|
+
3. Paste the following policy (already copied to clipboard):
|
|
523
|
+
|
|
524
|
+
{access_policy}
|
|
525
|
+
|
|
526
|
+
4. Name the policy something meaningful (e.g., TinybirdS3Access-{bucket})
|
|
527
|
+
5. Click "Create policy"
|
|
528
|
+
"""
|
|
502
529
|
)
|
|
530
|
+
click_enter_to_continue = prompt_message("\nPress Enter to continue...")
|
|
531
|
+
|
|
503
532
|
prompt_s3_iamrole_connection_policy_not_copied = prompt_message(
|
|
504
|
-
"""
|
|
533
|
+
"""
|
|
534
|
+
──────────────────────────────────────────────────────────────
|
|
535
|
+
STEP 2: CREATE IAM POLICY
|
|
536
|
+
──────────────────────────────────────────────────────────────
|
|
537
|
+
|
|
538
|
+
1. Go to \033]8;;https://console.aws.amazon.com/iamv2/home?region={aws_region}#/policies/create\033\\AWS IAM > Create Policy\033]8;;\033\\
|
|
539
|
+
2. Select the JSON tab
|
|
540
|
+
3. Copy and paste the following policy (replace <bucket> with your bucket name):
|
|
541
|
+
|
|
542
|
+
{access_policy}
|
|
543
|
+
|
|
544
|
+
4. Name the policy something meaningful (e.g., TinybirdS3Access-{bucket})
|
|
545
|
+
5. Click "Create policy"
|
|
546
|
+
"""
|
|
505
547
|
)
|
|
548
|
+
|
|
506
549
|
prompt_s3_iamrole_connection_role = prompt_message(
|
|
507
|
-
"""
|
|
550
|
+
"""
|
|
551
|
+
──────────────────────────────────────────────────────────────
|
|
552
|
+
STEP {step}: CREATE IAM ROLE FOR {environment} ENVIRONMENT
|
|
553
|
+
──────────────────────────────────────────────────────────────
|
|
554
|
+
|
|
555
|
+
1. Go to \033]8;;https://console.aws.amazon.com/iamv2/home?region={aws_region}#/roles/create\033\\AWS IAM > Create Role\033]8;;\033\\
|
|
556
|
+
2. Choose "Custom trust policy" and paste the following (already copied to clipboard):
|
|
557
|
+
|
|
558
|
+
{trust_policy}
|
|
559
|
+
|
|
560
|
+
3. Click Next, search for and select the policy you just created
|
|
561
|
+
4. Name the role something meaningful (e.g., TinybirdS3Role-{bucket}-{environment})
|
|
562
|
+
5. Click "Create role"
|
|
563
|
+
6. Copy the Role ARN from the role details page
|
|
564
|
+
|
|
565
|
+
Please enter the ARN of the role you just created"""
|
|
508
566
|
)
|
|
567
|
+
|
|
568
|
+
prompt_s3_iamrole_success_cloud = prompt_message(
|
|
569
|
+
"Would you like to create this connection in the cloud environment as well?"
|
|
570
|
+
)
|
|
571
|
+
|
|
509
572
|
prompt_s3_iamrole_connection_role_not_copied = prompt_message(
|
|
510
|
-
"""
|
|
573
|
+
"""
|
|
574
|
+
──────────────────────────────────────────────────────────────
|
|
575
|
+
STEP {step}: CREATE IAM ROLE FOR {environment} ENVIRONMENT
|
|
576
|
+
──────────────────────────────────────────────────────────────
|
|
577
|
+
|
|
578
|
+
1. Go to \033]8;;https://console.aws.amazon.com/iamv2/home?region={aws_region}#/roles/create\033\\AWS IAM > Create Role\033]8;;\033\\
|
|
579
|
+
2. Choose "Custom trust policy" and paste the following:
|
|
580
|
+
|
|
581
|
+
{trust_policy}
|
|
582
|
+
|
|
583
|
+
3. Click Next, search for and select the policy you just created
|
|
584
|
+
4. Name the role something meaningful (e.g., TinybirdS3Role-{bucket}-{environment})
|
|
585
|
+
5. Click "Create role"
|
|
586
|
+
6. Copy the Role ARN from the role details page
|
|
587
|
+
|
|
588
|
+
Please enter the ARN of the role you just created"""
|
|
511
589
|
)
|
|
590
|
+
|
|
591
|
+
prompt_s3_iamrole_success = success_message("""
|
|
592
|
+
✅ S3 CONNECTION CONFIGURED SUCCESSFULLY
|
|
593
|
+
|
|
594
|
+
• File created at: {connection_path}
|
|
595
|
+
• You can now use this connection in your Data Sources with: IMPORT_CONNECTION_NAME '{connection_name}'
|
|
596
|
+
• \033]8;;https://www.tinybird.co/docs/forward/get-data-in/connectors/s3\033\\Learn more about our S3 Connector\033]8;;\033\\
|
|
597
|
+
""")
|
|
598
|
+
|
|
512
599
|
prompt_init_git_release_pull = prompt_message(
|
|
513
600
|
"❓ Download the Data Project to continue, otherwise you can't initialize Workspace with Git. Execute '{pull_command}'?"
|
|
514
601
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
tinybird/__cli__.py,sha256=esPl5QDTzuQgHe5FuxWLm-fURFigGGwjnYLh9GuWUw4,232
|
|
2
2
|
tinybird/client.py,sha256=yc2BP2HiQhaUjU-t7nBuZEiJsb2nQMH3vBfOhKCciyU,55468
|
|
3
|
-
tinybird/config.py,sha256=
|
|
3
|
+
tinybird/config.py,sha256=iGOwxuWXpY82gBNoL71huJvQixe2IZEJ4jE3Y5thRA4,7548
|
|
4
4
|
tinybird/connectors.py,sha256=7Gjms7b5MAaBFGi3xytsJurCylprONpFcYrzp4Fw2Rc,15241
|
|
5
5
|
tinybird/context.py,sha256=FfqYfrGX_I7PKGTQo93utaKPDNVYWelg4Hsp3evX5wM,1291
|
|
6
6
|
tinybird/datatypes.py,sha256=XNypumfqNjsvLJ5iNXnbVHRvAJe0aQwI3lS6Cxox-e0,10979
|
|
@@ -15,22 +15,22 @@ tinybird/syncasync.py,sha256=IPnOx6lMbf9SNddN1eBtssg8vCLHMt76SuZ6YNYm-Yk,27761
|
|
|
15
15
|
tinybird/tornado_template.py,sha256=jjNVDMnkYFWXflmT8KU_Ssbo5vR8KQq3EJMk5vYgXRw,41959
|
|
16
16
|
tinybird/ch_utils/constants.py,sha256=aYvg2C_WxYWsnqPdZB1ZFoIr8ZY-XjUXYyHKE9Ansj0,3890
|
|
17
17
|
tinybird/ch_utils/engine.py,sha256=BZuPM7MFS7vaEKK5tOMR2bwSAgJudPrJt27uVEwZmTY,40512
|
|
18
|
-
tinybird/tb/__cli__.py,sha256=
|
|
18
|
+
tinybird/tb/__cli__.py,sha256=yrZISOnuZA2cFwARxKlPwsNs0Ot_jk2nvuUtNLbV6_g,252
|
|
19
19
|
tinybird/tb/cli.py,sha256=uDLwcbwSJfVFw-pceijZJqaq26z5jNsey0QaUGFjt7w,1097
|
|
20
20
|
tinybird/tb/modules/auth.py,sha256=NF0yfkGGBOtZRot-JPYbLD53i2kQ6lxJMD1140xtfzc,9034
|
|
21
21
|
tinybird/tb/modules/build.py,sha256=Lx1Q-kcxJN0G3pN3qCD8c8RmTpsmMoxCPhmn4DS2QMM,15563
|
|
22
22
|
tinybird/tb/modules/cicd.py,sha256=A7zJZF9HkJ6NPokplgNjmefMrpUlRbFxBbjMZhq5OTI,7110
|
|
23
23
|
tinybird/tb/modules/cli.py,sha256=cyvTGb17eWHdfI61Rom0ooD5D2aI1gRqx2nSi1gqtWA,16143
|
|
24
|
-
tinybird/tb/modules/common.py,sha256=
|
|
24
|
+
tinybird/tb/modules/common.py,sha256=IP9SHV7Qv0YFUcZiJrkUf4NeHRzt2a6uwsL9p_QK9ms,83990
|
|
25
25
|
tinybird/tb/modules/config.py,sha256=FqdLpLaKpYubqw3xkB4EX06ufZYDgGRxONR_9i-y-KE,11416
|
|
26
|
-
tinybird/tb/modules/connection.py,sha256=
|
|
26
|
+
tinybird/tb/modules/connection.py,sha256=fhpkAGhY5mqFVqXn69B90ngaKX88rXznlMGjohDgqpM,6336
|
|
27
27
|
tinybird/tb/modules/copy.py,sha256=MAVqKip8_QhOYq99U_XuqSO6hCLJEh5sFtbhcXtI3SI,5802
|
|
28
|
-
tinybird/tb/modules/create.py,sha256=
|
|
28
|
+
tinybird/tb/modules/create.py,sha256=K851M8N6kDemUDJUs3ukUWPl6G6z2CVnlME13ttDutk,16573
|
|
29
29
|
tinybird/tb/modules/datasource.py,sha256=dNCK9iCR2xPLfwqqwg2ixyE6NuoVEiJU2mBZBmOYrVY,16906
|
|
30
|
-
tinybird/tb/modules/deployment.py,sha256=
|
|
30
|
+
tinybird/tb/modules/deployment.py,sha256=4Zt7jPbqt18fB5kPx7DbO91Bh6xzBBTEUFY7O89shuU,19560
|
|
31
31
|
tinybird/tb/modules/endpoint.py,sha256=EhVoGAXsFz-83Fiwj1gI-I73iRRvL49d0W81un7hvPE,12080
|
|
32
32
|
tinybird/tb/modules/exceptions.py,sha256=4A2sSjCEqKUMqpP3WI00zouCWW4uLaghXXLZBSw04mY,3363
|
|
33
|
-
tinybird/tb/modules/feedback_manager.py,sha256=
|
|
33
|
+
tinybird/tb/modules/feedback_manager.py,sha256=4Somda9qWcibNRteE-aj50WpQ4gdEzhdpY6mh1LiGL0,73984
|
|
34
34
|
tinybird/tb/modules/fmt.py,sha256=qpf9APqKTKL2uphNgdbj4OMVyLkAxZn6dn4eHF99L5g,3553
|
|
35
35
|
tinybird/tb/modules/infra.py,sha256=fnbsfx8paRE8RHPbjdSOiOEvtyQbJ95OrHZuCighgKA,33203
|
|
36
36
|
tinybird/tb/modules/job.py,sha256=956Pj8BEEsiD2GZsV9RKKVM3I_CveOLgS82lykO5ukk,2963
|
|
@@ -80,8 +80,8 @@ tinybird/tb_cli_modules/config.py,sha256=IsgdtFRnUrkY8-Zo32lmk6O7u3bHie1QCxLwgp4
|
|
|
80
80
|
tinybird/tb_cli_modules/exceptions.py,sha256=pmucP4kTF4irIt7dXiG-FcnI-o3mvDusPmch1L8RCWk,3367
|
|
81
81
|
tinybird/tb_cli_modules/regions.py,sha256=QjsL5H6Kg-qr0aYVLrvb1STeJ5Sx_sjvbOYO0LrEGMk,166
|
|
82
82
|
tinybird/tb_cli_modules/telemetry.py,sha256=Hh2Io8ZPROSunbOLuMvuIFU4TqwWPmQTqal4WS09K1A,10449
|
|
83
|
-
tinybird-0.0.1.
|
|
84
|
-
tinybird-0.0.1.
|
|
85
|
-
tinybird-0.0.1.
|
|
86
|
-
tinybird-0.0.1.
|
|
87
|
-
tinybird-0.0.1.
|
|
83
|
+
tinybird-0.0.1.dev118.dist-info/METADATA,sha256=V_RQFDErCfGK_9Vb-dCuA9CsNMC3V-wkVlcgxIqDuVc,1612
|
|
84
|
+
tinybird-0.0.1.dev118.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
85
|
+
tinybird-0.0.1.dev118.dist-info/entry_points.txt,sha256=LwdHU6TfKx4Qs7BqqtaczEZbImgU7Abe9Lp920zb_fo,43
|
|
86
|
+
tinybird-0.0.1.dev118.dist-info/top_level.txt,sha256=VqqqEmkAy7UNaD8-V51FCoMMWXjLUlR0IstvK7tJYVY,54
|
|
87
|
+
tinybird-0.0.1.dev118.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|