tinybird 0.0.1.dev111__tar.gz → 0.0.1.dev113__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.

Files changed (108) hide show
  1. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/PKG-INFO +1 -1
  2. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/prompts.py +32 -0
  3. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/__cli__.py +2 -2
  4. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/cicd.py +7 -0
  5. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/cli.py +8 -1
  6. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/common.py +60 -86
  7. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/connection.py +42 -0
  8. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/create.py +60 -2
  9. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/datafile/fixture.py +3 -1
  10. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/feedback_manager.py +1 -1
  11. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/infra.py +1 -1
  12. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird.egg-info/PKG-INFO +1 -1
  13. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/setup.cfg +0 -0
  14. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/__cli__.py +0 -0
  15. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/ch_utils/constants.py +0 -0
  16. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/ch_utils/engine.py +0 -0
  17. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/check_pypi.py +0 -0
  18. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/client.py +0 -0
  19. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/config.py +0 -0
  20. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/connectors.py +0 -0
  21. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/context.py +0 -0
  22. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/datafile.py +0 -0
  23. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/datatypes.py +0 -0
  24. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/feedback_manager.py +0 -0
  25. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/git_settings.py +0 -0
  26. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/sql.py +0 -0
  27. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/sql_template.py +0 -0
  28. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/sql_template_fmt.py +0 -0
  29. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/sql_toolset.py +0 -0
  30. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/syncasync.py +0 -0
  31. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/cli.py +0 -0
  32. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/auth.py +0 -0
  33. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/build.py +0 -0
  34. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/config.py +0 -0
  35. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/copy.py +0 -0
  36. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/datafile/build.py +0 -0
  37. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/datafile/build_common.py +0 -0
  38. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/datafile/build_datasource.py +0 -0
  39. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/datafile/build_pipe.py +0 -0
  40. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/datafile/common.py +0 -0
  41. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/datafile/diff.py +0 -0
  42. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/datafile/exceptions.py +0 -0
  43. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/datafile/format_common.py +0 -0
  44. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/datafile/format_datasource.py +0 -0
  45. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/datafile/format_pipe.py +0 -0
  46. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/datafile/parse_datasource.py +0 -0
  47. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/datafile/parse_pipe.py +0 -0
  48. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/datafile/pipe_checker.py +0 -0
  49. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/datafile/playground.py +0 -0
  50. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/datafile/pull.py +0 -0
  51. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/datasource.py +0 -0
  52. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/deployment.py +0 -0
  53. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/endpoint.py +0 -0
  54. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/exceptions.py +0 -0
  55. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/fmt.py +0 -0
  56. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/job.py +0 -0
  57. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/llm.py +0 -0
  58. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/llm_utils.py +0 -0
  59. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/local.py +0 -0
  60. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/local_common.py +0 -0
  61. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/login.py +0 -0
  62. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/logout.py +0 -0
  63. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/materialization.py +0 -0
  64. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/mock.py +0 -0
  65. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/open.py +0 -0
  66. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/pipe.py +0 -0
  67. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/playground.py +0 -0
  68. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/project.py +0 -0
  69. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/regions.py +0 -0
  70. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/secret.py +0 -0
  71. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/shell.py +0 -0
  72. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/table.py +0 -0
  73. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/tag.py +0 -0
  74. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/telemetry.py +0 -0
  75. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/test.py +0 -0
  76. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/tinyunit/tinyunit.py +0 -0
  77. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/tinyunit/tinyunit_lib.py +0 -0
  78. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/token.py +0 -0
  79. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/watch.py +0 -0
  80. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/workspace.py +0 -0
  81. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb/modules/workspace_members.py +0 -0
  82. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb_cli.py +0 -0
  83. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb_cli_modules/auth.py +0 -0
  84. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb_cli_modules/branch.py +0 -0
  85. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb_cli_modules/cicd.py +0 -0
  86. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb_cli_modules/cli.py +0 -0
  87. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb_cli_modules/common.py +0 -0
  88. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb_cli_modules/config.py +0 -0
  89. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb_cli_modules/connection.py +0 -0
  90. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb_cli_modules/datasource.py +0 -0
  91. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb_cli_modules/exceptions.py +0 -0
  92. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb_cli_modules/fmt.py +0 -0
  93. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb_cli_modules/job.py +0 -0
  94. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb_cli_modules/pipe.py +0 -0
  95. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb_cli_modules/regions.py +0 -0
  96. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb_cli_modules/tag.py +0 -0
  97. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb_cli_modules/telemetry.py +0 -0
  98. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb_cli_modules/test.py +0 -0
  99. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
  100. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
  101. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb_cli_modules/workspace.py +0 -0
  102. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tb_cli_modules/workspace_members.py +0 -0
  103. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird/tornado_template.py +0 -0
  104. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird.egg-info/SOURCES.txt +0 -0
  105. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird.egg-info/dependency_links.txt +0 -0
  106. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird.egg-info/entry_points.txt +0 -0
  107. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/tinybird.egg-info/requires.txt +0 -0
  108. {tinybird-0.0.1.dev111 → tinybird-0.0.1.dev113}/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.dev111
3
+ Version: 0.0.1.dev113
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/cli/introduction.html
6
6
  Author: Tinybird
@@ -954,3 +954,35 @@ FORWARD_QUERY >
954
954
  </forward_query_example>
955
955
  </deployment_instruction>
956
956
  """
957
+
958
+
959
+ def readme_prompt(readme: str, host: str, token: str, resources_xml: str) -> str:
960
+ return f"""
961
+ You are an expert in SQL and Tinybird. Follow these instructions to generate a new README.md file for a tinybird project:
962
+ Current README.md file:
963
+ <current_resources_xml>
964
+ {resources_xml}
965
+ </current_resources_xml>
966
+ <readme>{readme}</readme>
967
+ <readme_instructions>
968
+ - If it is not present in the current readme, generate a new ## Tinybird section with the following content:
969
+ - ### Overview section:
970
+ - Explaining the purpose of the project.
971
+ - ### Data sources section:
972
+ - Explaining the purpose of each datasource.
973
+ - Add a snippet of how to ingest data into each datasource like the following (where the payload example matches the datasource schema respecting non-nullable types):
974
+ curl -X POST "{host}/v0/events?name=events" \
975
+ -H "Authorization: Bearer {token}" \
976
+ -d '{{"date":"2025-01-31","id":"123","user_id":"abc"}}'
977
+ - ### Endpoints section:
978
+ - Explaining the purpose of each endpoint.
979
+ - Add a snippet of how to use each endpoint like the following:
980
+ curl -X GET "{host}/v0/pipes/pipe_name.json?token={token}"
981
+ - DateTime parameters must be formatted as YYYY-MM-DD HH:MM:SS, or else will fail.
982
+ - Do not include any other extra info related to Tinybird just maintain the existing one in the <readme> tag.
983
+ - Make sure the API host is correct, {host}.
984
+ - It is mandatory to return a <resource> tag with type "readme" in the response.
985
+ - The response must follow the following format:
986
+ <readme>[readme content here]</readme>
987
+ </readme_instructions>
988
+ """
@@ -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.dev111'
8
- __revision__ = '621864a'
7
+ __version__ = '0.0.1.dev113'
8
+ __revision__ = '49946d6'
@@ -120,7 +120,9 @@ tinybird_ci_workflow:
120
120
  services:
121
121
  - name: tinybirdco/tinybird-local:beta
122
122
  alias: tinybird-local
123
+ """
123
124
 
125
+ GITLAB_CD_YML = """
124
126
  tinybird_cd_workflow:
125
127
  image: ubuntu:latest
126
128
  stage: deploy
@@ -217,6 +219,11 @@ class GitLabCICDGenerator(CICDGeneratorBase):
217
219
  file_name="tinybird-ci.yml",
218
220
  dir_path=".gitlab/tinybird",
219
221
  ),
222
+ CICDFile(
223
+ template=GITLAB_CD_YML,
224
+ file_name="tinybird-cd.yml",
225
+ dir_path=".gitlab/tinybird",
226
+ ),
220
227
  ]
221
228
 
222
229
 
@@ -6,6 +6,7 @@
6
6
  import json
7
7
  import logging
8
8
  import os
9
+ import shutil
9
10
  import sys
10
11
  from os import getcwd
11
12
  from pathlib import Path
@@ -48,7 +49,13 @@ DEFAULT_PATTERNS: List[Tuple[str, Union[str, Callable[[str], str]]]] = [
48
49
  VERSION = f"{__cli__.__version__} (rev {__cli__.__revision__})"
49
50
 
50
51
 
51
- @click.group(cls=CatchAuthExceptions, context_settings={"help_option_names": ["-h", "--help"]})
52
+ @click.group(
53
+ cls=CatchAuthExceptions,
54
+ context_settings={
55
+ "help_option_names": ["-h", "--help"],
56
+ "max_content_width": shutil.get_terminal_size().columns - 10,
57
+ },
58
+ )
52
59
  @click.option(
53
60
  "--debug/--no-debug",
54
61
  default=False,
@@ -1751,90 +1751,69 @@ async def remove_release(
1751
1751
  click.echo(FeedbackManager.info_no_release_deleted())
1752
1752
 
1753
1753
 
1754
- async def validate_aws_iamrole_integration(
1754
+ async def run_aws_iamrole_connection_flow(
1755
1755
  client: TinyB,
1756
1756
  service: str,
1757
- role_arn: Optional[str],
1758
- region: Optional[str],
1759
- policy: str = "write",
1760
- no_validate: Optional[bool] = False,
1757
+ policy: str = "read",
1761
1758
  ):
1762
- if no_validate is False:
1763
- access_policy, trust_policy, external_id = await get_aws_iamrole_policies(
1764
- client, service=service, policy=policy
1765
- )
1759
+ if service == DataConnectorType.AMAZON_DYNAMODB:
1760
+ raise NotImplementedError("DynamoDB is not supported yet")
1766
1761
 
1767
- if not role_arn:
1768
- if not click.confirm(
1769
- FeedbackManager.prompt_s3_iamrole_connection_login_aws(),
1770
- show_default=False,
1771
- prompt_suffix="Press y to continue:",
1772
- ):
1773
- sys.exit(1)
1762
+ resource_type = "table" if service == DataConnectorType.AMAZON_DYNAMODB else "bucket"
1763
+ resource_name = click.prompt(f"Enter the name of the {resource_type}")
1764
+ validate_string_connector_param(resource_type.capitalize(), resource_name)
1774
1765
 
1775
- access_policy_copied = True
1776
- try:
1777
- pyperclip.copy(access_policy)
1778
- except Exception:
1779
- access_policy_copied = False
1766
+ resource_region = click.prompt(f"Enter the region where the {resource_type} is located")
1767
+ validate_string_connector_param("Region", resource_region)
1780
1768
 
1781
- replacements_dict = {
1782
- "<bucket>": "<bucket> with your bucket name",
1783
- "<table_name>": "<table_name> with your DynamoDB table name",
1784
- }
1769
+ access_policy, trust_policy, external_id = await get_aws_iamrole_policies(client, service=service, policy=policy)
1770
+ access_policy = access_policy.replace("<bucket>", resource_name)
1785
1771
 
1786
- replacements = [
1787
- replacements_dict.get(replacement, "")
1788
- for replacement in replacements_dict.keys()
1789
- if replacement in access_policy
1790
- ]
1772
+ if not click.confirm(
1773
+ FeedbackManager.prompt_s3_iamrole_connection_login_aws(),
1774
+ show_default=False,
1775
+ prompt_suffix="Press y to continue:",
1776
+ ):
1777
+ sys.exit(1)
1791
1778
 
1792
- if not click.confirm(
1793
- (
1794
- FeedbackManager.prompt_s3_iamrole_connection_policy(
1795
- access_policy=access_policy, replacements=", ".join(replacements)
1796
- )
1797
- if access_policy_copied
1798
- else FeedbackManager.prompt_s3_iamrole_connection_policy_not_copied(access_policy=access_policy)
1799
- ),
1800
- show_default=False,
1801
- prompt_suffix="Press y to continue:",
1802
- ):
1803
- sys.exit(1)
1804
-
1805
- trust_policy_copied = True
1806
- try:
1807
- pyperclip.copy(trust_policy)
1808
- except Exception:
1809
- trust_policy_copied = False
1810
-
1811
- if not click.confirm(
1812
- (
1813
- FeedbackManager.prompt_s3_iamrole_connection_role(trust_policy=trust_policy)
1814
- if trust_policy_copied
1815
- else FeedbackManager.prompt_s3_iamrole_connection_role_not_copied(trust_policy=trust_policy)
1816
- ),
1817
- show_default=False,
1818
- prompt_suffix="Press y to continue:",
1819
- ):
1820
- sys.exit(1)
1821
- else:
1822
- try:
1823
- trust_policy = await client.get_trust_policy(service)
1824
- external_id = trust_policy["Statement"][0]["Condition"]["StringEquals"]["sts:ExternalId"]
1825
- except Exception:
1826
- external_id = ""
1779
+ access_policy_copied = True
1780
+ try:
1781
+ pyperclip.copy(access_policy)
1782
+ except Exception:
1783
+ access_policy_copied = False
1827
1784
 
1828
- if not role_arn:
1829
- role_arn = click.prompt("Enter the ARN of the role you just created")
1830
- validate_string_connector_param("Role ARN", role_arn)
1785
+ if not click.confirm(
1786
+ (
1787
+ FeedbackManager.prompt_s3_iamrole_connection_policy(access_policy=access_policy)
1788
+ if access_policy_copied
1789
+ else FeedbackManager.prompt_s3_iamrole_connection_policy_not_copied(access_policy=access_policy)
1790
+ ),
1791
+ show_default=False,
1792
+ prompt_suffix="Press y to continue:",
1793
+ ):
1794
+ sys.exit(1)
1831
1795
 
1832
- if not region:
1833
- region_resource = "table" if service == DataConnectorType.AMAZON_DYNAMODB else "bucket"
1834
- region = click.prompt(f"Enter the region where the {region_resource} is located")
1835
- validate_string_connector_param("Region", region)
1796
+ trust_policy_copied = True
1797
+ try:
1798
+ pyperclip.copy(trust_policy)
1799
+ except Exception:
1800
+ trust_policy_copied = False
1836
1801
 
1837
- return role_arn, region, external_id
1802
+ if not click.confirm(
1803
+ (
1804
+ FeedbackManager.prompt_s3_iamrole_connection_role(trust_policy=trust_policy)
1805
+ if trust_policy_copied
1806
+ else FeedbackManager.prompt_s3_iamrole_connection_role_not_copied(trust_policy=trust_policy)
1807
+ ),
1808
+ show_default=False,
1809
+ prompt_suffix="Press y to continue:",
1810
+ ):
1811
+ sys.exit(1)
1812
+
1813
+ role_arn = click.prompt("Enter the ARN of the role you just created")
1814
+ validate_string_connector_param("Role ARN", role_arn)
1815
+
1816
+ return role_arn, resource_region, external_id
1838
1817
 
1839
1818
 
1840
1819
  async def get_aws_iamrole_policies(client: TinyB, service: str, policy: str = "write"):
@@ -1867,20 +1846,15 @@ async def get_aws_iamrole_policies(client: TinyB, service: str, policy: str = "w
1867
1846
  return json.dumps(access_policy, indent=4), json.dumps(trust_policy, indent=4), external_id
1868
1847
 
1869
1848
 
1870
- async def validate_aws_iamrole_connection_name(
1871
- client: TinyB, connection_name: Optional[str], no_validate: Optional[bool] = False
1872
- ) -> str:
1873
- if connection_name and no_validate is False:
1874
- if await client.get_connector(connection_name, skip_bigquery=True) is not None:
1875
- raise CLIConnectionException(FeedbackManager.info_connection_already_exists(name=connection_name))
1876
- else:
1877
- while not connection_name:
1878
- connection_name = click.prompt("Enter the name for this connection", default=None, show_default=False)
1879
- assert isinstance(connection_name, str)
1849
+ async def validate_aws_iamrole_connection_name(client: TinyB) -> str:
1850
+ connection_name = None
1851
+ while not connection_name:
1852
+ connection_name = click.prompt("Enter the name for this connection", default=None, show_default=False)
1853
+ assert isinstance(connection_name, str)
1880
1854
 
1881
- if no_validate is False and await client.get_connector(connection_name) is not None:
1882
- click.echo(FeedbackManager.info_connection_already_exists(name=connection_name))
1883
- connection_name = None
1855
+ if await client.get_connector(connection_name) is not None:
1856
+ click.echo(FeedbackManager.info_connection_already_exists(name=connection_name))
1857
+ connection_name = None
1884
1858
  assert isinstance(connection_name, str)
1885
1859
  return connection_name
1886
1860
 
@@ -15,8 +15,12 @@ from tinybird.tb.modules.common import (
15
15
  _get_setting_value,
16
16
  coro,
17
17
  echo_safe_humanfriendly_tables_format_smart_table,
18
+ run_aws_iamrole_connection_flow,
19
+ validate_aws_iamrole_connection_name,
18
20
  )
21
+ from tinybird.tb.modules.create import generate_aws_iamrole_connection_file
19
22
  from tinybird.tb.modules.feedback_manager import FeedbackManager
23
+ from tinybird.tb.modules.project import Project
20
24
 
21
25
  DATA_CONNECTOR_SETTINGS: Dict[DataConnectorType, List[str]] = {
22
26
  DataConnectorType.KAFKA: [
@@ -123,3 +127,41 @@ async def connection_ls(ctx: Context, service: Optional[DataConnectorType] = Non
123
127
  column_names = [c.replace("kafka_", "") for c in columns]
124
128
  echo_safe_humanfriendly_tables_format_smart_table(table, column_names=column_names)
125
129
  click.echo("\n")
130
+
131
+
132
+ @connection.group(name="create")
133
+ @click.pass_context
134
+ def connection_create(ctx: Context) -> None:
135
+ """Create a connection."""
136
+
137
+
138
+ @connection_create.command(name="s3", short_help="Creates a AWS S3 connection.")
139
+ @click.pass_context
140
+ @coro
141
+ async def connection_create_s3(ctx: Context) -> None:
142
+ """
143
+ Creates a AWS S3 connection.
144
+
145
+ \b
146
+ $ tb connection create s3
147
+ """
148
+ project: Project = ctx.ensure_object(dict)["project"]
149
+ obj: Dict[str, Any] = ctx.ensure_object(dict)
150
+ client: TinyB = obj["client"]
151
+ service = DataConnectorType.AMAZON_S3
152
+ connection_name = await validate_aws_iamrole_connection_name(client)
153
+ role_arn, region, external_id = await run_aws_iamrole_connection_flow(
154
+ client,
155
+ service=service,
156
+ policy="read", # For now only read since we only support import from S3
157
+ )
158
+
159
+ await generate_aws_iamrole_connection_file(
160
+ name=connection_name, service=service, role_arn=role_arn, region=region, folder=project.folder
161
+ )
162
+ if external_id:
163
+ click.echo(
164
+ FeedbackManager.success_s3_iam_connection_created(
165
+ connection_name=connection_name, external_id=external_id, role_arn=role_arn
166
+ )
167
+ )
@@ -6,7 +6,7 @@ from typing import Optional, Tuple
6
6
  import click
7
7
 
8
8
  from tinybird.client import TinyB
9
- from tinybird.prompts import create_prompt, mock_prompt, rules_prompt
9
+ from tinybird.prompts import create_prompt, mock_prompt, readme_prompt, rules_prompt
10
10
  from tinybird.tb.modules.cicd import init_cicd
11
11
  from tinybird.tb.modules.cli import cli
12
12
  from tinybird.tb.modules.common import _generate_datafile, coro, generate_datafile
@@ -88,12 +88,32 @@ async def create(
88
88
  click.echo(FeedbackManager.success(message="✓ Scaffolding completed!\n"))
89
89
  created_something = True
90
90
  result = ""
91
- if data or prompt:
91
+ if (data or prompt) and user_token:
92
92
  click.echo(FeedbackManager.highlight(message="\n» Creating resources..."))
93
93
  result, created_something = await create_resources(
94
94
  local_client, tb_client, user_token, data, prompt, folder
95
95
  )
96
96
  click.echo(FeedbackManager.success(message="✓ Done!\n"))
97
+ if prompt:
98
+ readme_path = Path(root_folder) / "README.md"
99
+ if readme_path.exists():
100
+ click.echo(FeedbackManager.highlight(message="\n» Updating README.md..."))
101
+ else:
102
+ click.echo(FeedbackManager.highlight(message="\n» Creating README.md..."))
103
+ readme_path.touch()
104
+ llm = LLM(user_token=str(user_token), host=tb_client.host)
105
+ readme_user_prompt = prompt or ""
106
+ all_resources_xml = get_resources_xml(project)
107
+ readme_response = llm.ask(
108
+ system_prompt=readme_prompt(
109
+ readme_path.read_text(), tb_client.host, tb_client.token, all_resources_xml
110
+ ),
111
+ prompt=readme_user_prompt,
112
+ )
113
+ readme_result = extract_xml(readme_response, "readme")
114
+ readme_path.write_text(readme_result)
115
+ click.echo(FeedbackManager.success(message="✓ Done!\n"))
116
+ created_something = True
97
117
 
98
118
  if not already_has_cicd(root_folder):
99
119
  click.echo(FeedbackManager.highlight(message="\n» Creating CI/CD files for GitHub and GitLab..."))
@@ -353,6 +373,17 @@ def generate_connection_file(name: str, content: str, folder: str) -> Path:
353
373
  return f.relative_to(folder)
354
374
 
355
375
 
376
+ async def generate_aws_iamrole_connection_file(
377
+ name: str, service: str, role_arn: str, region: str, folder: str
378
+ ) -> None:
379
+ content = f"""TYPE {service}
380
+
381
+ S3_ARN {role_arn}
382
+ S3_REGION {region}
383
+ """
384
+ generate_connection_file(name, content, folder)
385
+
386
+
356
387
  def create_rules(folder: str, source: str, agent: str):
357
388
  if agent == "cursor":
358
389
  extension = ".cursorrules"
@@ -379,3 +410,30 @@ def get_context() -> str:
379
410
  def save_context(prompt: str, feedback: str):
380
411
  context_file = get_context_file()
381
412
  context_file.write_text(f"- {prompt}\n{feedback}")
413
+
414
+
415
+ def get_resources_xml(project: Project) -> str:
416
+ folder = project.folder
417
+ datasource_paths = [
418
+ Path(folder) / "datasources" / f for f in os.listdir(Path(folder) / "datasources") if f.endswith(".datasource")
419
+ ]
420
+ pipes_paths = [
421
+ Path(folder) / "endpoints" / f for f in os.listdir(Path(folder) / "endpoints") if f.endswith(".pipe")
422
+ ]
423
+ resources_xml = "\n".join(
424
+ [
425
+ f"<resource><type>{resource_type}</type><name>{resource_name}</name><content>{resource_content}</content></resource>"
426
+ for resource_type, resource_name, resource_content in [
427
+ ("datasource", ds.stem, ds.read_text()) for ds in datasource_paths
428
+ ]
429
+ + [
430
+ (
431
+ "pipe",
432
+ pipe.stem,
433
+ pipe.read_text(),
434
+ )
435
+ for pipe in pipes_paths
436
+ ]
437
+ ]
438
+ )
439
+ return resources_xml
@@ -5,7 +5,9 @@ from tinybird.tb.modules.common import format_data_to_ndjson
5
5
 
6
6
 
7
7
  def get_fixture_dir(folder: str) -> Path:
8
- return Path(folder) / "fixtures"
8
+ fixture_dir = Path(folder) / "fixtures"
9
+ fixture_dir.mkdir(exist_ok=True)
10
+ return fixture_dir
9
11
 
10
12
 
11
13
  def persist_fixture_sql(fixture_name: str, sql: str, folder: str) -> Path:
@@ -498,7 +498,7 @@ Ready? """
498
498
 
499
499
  prompt_s3_iamrole_connection_login_aws = prompt_message("""[1] Log into your AWS Console\n\n""")
500
500
  prompt_s3_iamrole_connection_policy = prompt_message(
501
- """\n[2] Go to IAM > Policies. Create a new policy with the following permissions. Please, replace {replacements}:\n\n{access_policy}\n\n(The policy has been copied to your clipboard)\n\n"""
501
+ """\n[2] Go to IAM > Policies. Create a new policy with the following permissions:\n\n{access_policy}\n\n(The policy has been copied to your clipboard)\n\n"""
502
502
  )
503
503
  prompt_s3_iamrole_connection_policy_not_copied = prompt_message(
504
504
  """\n[2] Go to IAM > Policies. Create a new policy with the following permissions. Please, copy this policy and replace <bucket> with your bucket name:\n\n{access_policy}\n\n"""
@@ -371,7 +371,7 @@ async def infra_init(
371
371
 
372
372
  # Create infra directory if it doesn't exist
373
373
  infra_dir = Path(f"infra/{cloud_provider}")
374
- infra_dir.mkdir(exist_ok=True)
374
+ infra_dir.mkdir(parents=True, exist_ok=True)
375
375
  yaml_path = infra_dir / "k8s.yaml"
376
376
  tf_path = infra_dir / "main.tf"
377
377
  config_path = infra_dir / "config.json"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: tinybird
3
- Version: 0.0.1.dev111
3
+ Version: 0.0.1.dev113
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/cli/introduction.html
6
6
  Author: Tinybird