validio-cli 0.18.2__tar.gz → 0.20.0__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 (26) hide show
  1. {validio_cli-0.18.2 → validio_cli-0.20.0}/PKG-INFO +2 -2
  2. {validio_cli-0.18.2 → validio_cli-0.20.0}/pyproject.toml +2 -2
  3. {validio_cli-0.18.2 → validio_cli-0.20.0}/validio_cli/bin/entities/channels.py +1 -1
  4. {validio_cli-0.18.2 → validio_cli-0.20.0}/validio_cli/bin/entities/code.py +71 -2
  5. {validio_cli-0.18.2 → validio_cli-0.20.0}/validio_cli/bin/entities/config.py +6 -4
  6. {validio_cli-0.18.2 → validio_cli-0.20.0}/validio_cli/bin/entities/notification_rules.py +1 -1
  7. {validio_cli-0.18.2 → validio_cli-0.20.0}/validio_cli/bin/entities/users.py +1 -1
  8. {validio_cli-0.18.2 → validio_cli-0.20.0}/LICENSE +0 -0
  9. {validio_cli-0.18.2 → validio_cli-0.20.0}/README_PUBLIC.md +0 -0
  10. {validio_cli-0.18.2 → validio_cli-0.20.0}/validio_cli/__init__.py +0 -0
  11. {validio_cli-0.18.2 → validio_cli-0.20.0}/validio_cli/bin/entities/credentials.py +0 -0
  12. {validio_cli-0.18.2 → validio_cli-0.20.0}/validio_cli/bin/entities/dbt.py +0 -0
  13. {validio_cli-0.18.2 → validio_cli-0.20.0}/validio_cli/bin/entities/incidents.py +0 -0
  14. {validio_cli-0.18.2 → validio_cli-0.20.0}/validio_cli/bin/entities/metrics.py +0 -0
  15. {validio_cli-0.18.2 → validio_cli-0.20.0}/validio_cli/bin/entities/recommendations.py +0 -0
  16. {validio_cli-0.18.2 → validio_cli-0.20.0}/validio_cli/bin/entities/resources.py +0 -0
  17. {validio_cli-0.18.2 → validio_cli-0.20.0}/validio_cli/bin/entities/segmentations.py +0 -0
  18. {validio_cli-0.18.2 → validio_cli-0.20.0}/validio_cli/bin/entities/segments.py +0 -0
  19. {validio_cli-0.18.2 → validio_cli-0.20.0}/validio_cli/bin/entities/sources.py +0 -0
  20. {validio_cli-0.18.2 → validio_cli-0.20.0}/validio_cli/bin/entities/validators.py +0 -0
  21. {validio_cli-0.18.2 → validio_cli-0.20.0}/validio_cli/bin/entities/windows.py +0 -0
  22. {validio_cli-0.18.2 → validio_cli-0.20.0}/validio_cli/bin/main.py +0 -0
  23. {validio_cli-0.18.2 → validio_cli-0.20.0}/validio_cli/components.py +0 -0
  24. {validio_cli-0.18.2 → validio_cli-0.20.0}/validio_cli/metadata.py +0 -0
  25. {validio_cli-0.18.2 → validio_cli-0.20.0}/validio_cli/namespace.py +0 -0
  26. {validio_cli-0.18.2 → validio_cli-0.20.0}/validio_cli/schema.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: validio-cli
3
- Version: 0.18.2
3
+ Version: 0.20.0
4
4
  Summary: CLI tool to interact with the Validio platform
5
5
  Home-page: https://validio.io/
6
6
  License: Apache-2.0
@@ -12,7 +12,7 @@ Classifier: Programming Language :: Python :: 3
12
12
  Classifier: Programming Language :: Python :: 3.10
13
13
  Classifier: Programming Language :: Python :: 3.11
14
14
  Requires-Dist: camel-converter (>=3.0.0,<4.0.0)
15
- Requires-Dist: classdiff (==0.4.0)
15
+ Requires-Dist: classdiff (>=0.5.0,<0.6.0)
16
16
  Requires-Dist: prompt-toolkit (>=3.0.38,<4.0.0)
17
17
  Requires-Dist: pydantic (==2.4.2)
18
18
  Requires-Dist: tabulate (>=0.9.0,<0.10.0)
@@ -3,7 +3,7 @@ name = "validio-cli"
3
3
  # This version does not represent the released version or any tag. For each
4
4
  # release we automatically bump this before building and publishing so this
5
5
  # should be kept at 0.0.1dev1
6
- version = "0.18.2"
6
+ version = "0.20.0"
7
7
  description = "CLI tool to interact with the Validio platform"
8
8
  authors = ["Validio <support@validio.io>"]
9
9
  license = "Apache-2.0"
@@ -15,7 +15,7 @@ readme = "README_PUBLIC.md"
15
15
  [tool.poetry.dependencies]
16
16
  python = "^3.10"
17
17
  camel-converter = "^3.0.0"
18
- classdiff = "0.4.0"
18
+ classdiff = "^0.5.0"
19
19
  validio-sdk = "*"
20
20
  typer = { extras = ["all"], version = "^0.7.0" }
21
21
  prompt-toolkit = "^3.0.38"
@@ -39,7 +39,7 @@ async def get(
39
39
  )
40
40
  ]
41
41
  else:
42
- channels = await vc.get_channels( # type: ignore
42
+ channels = await vc.list_channels( # type: ignore
43
43
  filter=ResourceFilter(namespace_id=ns)
44
44
  )
45
45
 
@@ -21,6 +21,9 @@ from validio_cli import AsyncTyper, ConfigDir, Namespace, get_client_and_config
21
21
  from validio_cli.bin.entities.resources import do_move
22
22
  from validio_cli.components import proceed_with_operation
23
23
 
24
+ """Maximum number of deprecation warnings to show."""
25
+ MAX_DEPRECATIONS_TO_SHOW = 20
26
+
24
27
  app = AsyncTyper(help="Plan or apply your configuration")
25
28
 
26
29
 
@@ -40,7 +43,7 @@ directory_option = typer.Option(
40
43
  ),
41
44
  )
42
45
 
43
- no_capture_option: bool = typer.Option(
46
+ no_capture_option = typer.Option(
44
47
  False,
45
48
  help=(
46
49
  "By default, the code program's stdout output is hidden; "
@@ -92,6 +95,16 @@ update_all_schemas_option = typer.Option(
92
95
  ),
93
96
  )
94
97
 
98
+ target_option = typer.Option(
99
+ [],
100
+ help=(
101
+ "[red][bold]BETA[/bold][/red] "
102
+ "Only target selected resources and ignore changes for others."
103
+ "Format is '<type>:<name>', e.g. 'source:my-bq-source' or "
104
+ "'window:my-global-window'"
105
+ ),
106
+ )
107
+
95
108
 
96
109
  @app.command(help="Initialize a new IaC project")
97
110
  def init(
@@ -120,6 +133,7 @@ async def plan(
120
133
  destroy: bool = destroy_option,
121
134
  show_secrets: bool = show_secrets_option,
122
135
  color: bool = color_option,
136
+ target: list[str] = target_option,
123
137
  ) -> None:
124
138
  dir_path = directory_or_default(directory)
125
139
  client, _ = await get_client_and_config(config_dir)
@@ -140,6 +154,7 @@ async def plan(
140
154
  show_schema=show_schema,
141
155
  diff_output=diff_output,
142
156
  show_secrets=show_secrets,
157
+ targets=set(target),
143
158
  )
144
159
 
145
160
 
@@ -158,6 +173,7 @@ async def apply(
158
173
  destroy: bool = destroy_option,
159
174
  show_secrets: bool = show_secrets_option,
160
175
  color: bool = color_option,
176
+ target: list[str] = target_option,
161
177
  ) -> None:
162
178
  dir_path = directory_or_default(directory)
163
179
  client, _ = await get_client_and_config(config_dir)
@@ -178,6 +194,7 @@ async def apply(
178
194
  show_schema=show_schema,
179
195
  diff_output=diff_output,
180
196
  show_secrets=show_secrets,
197
+ targets=set(target),
181
198
  )
182
199
 
183
200
  if diff.num_operations() == 0:
@@ -306,8 +323,9 @@ async def _plan(
306
323
  diff_output: DiffOutput = DiffOutput.FULL,
307
324
  show_secrets: bool = False,
308
325
  show_diff: bool = True,
326
+ targets: set[str] = set(),
309
327
  ) -> tuple[GraphDiff, DiffContext]:
310
- (diff, manifest_ctx) = await code_plan.plan(
328
+ plan_result = await code_plan.plan(
311
329
  namespace=namespace,
312
330
  client=client,
313
331
  directory=directory,
@@ -315,8 +333,11 @@ async def _plan(
315
333
  destroy=destroy,
316
334
  no_capture=no_capture,
317
335
  show_secrets=show_secrets,
336
+ targets=_create_resource_names(targets),
318
337
  )
319
338
 
339
+ diff, manifest_ctx = plan_result.graph_diff, plan_result.diff_context
340
+
320
341
  if show_diff:
321
342
  if diff.num_operations() == 0:
322
343
  _print_no_changes()
@@ -328,6 +349,7 @@ async def _plan(
328
349
  show_secrets=show_secrets,
329
350
  escape=sys.stdout.isatty() and color,
330
351
  diff_output=diff_output,
352
+ deprecations=plan_result.deprecations,
331
353
  )
332
354
 
333
355
  return diff, manifest_ctx
@@ -339,6 +361,7 @@ def _show_resources_diff(
339
361
  show_secrets: bool,
340
362
  escape: bool,
341
363
  diff_output: DiffOutput,
364
+ deprecations: list[code_plan.ResourceDeprecation],
342
365
  ) -> None:
343
366
  resource_types = DiffContext.fields()
344
367
  if diff.num_creates() > 0:
@@ -371,6 +394,8 @@ def _show_resources_diff(
371
394
  diff_output=diff_output,
372
395
  )
373
396
 
397
+ _show_deprecations(deprecations)
398
+
374
399
  print(
375
400
  "\n"
376
401
  f"Plan: {diff.num_creates()} to create, {diff.num_updates()} to update, "
@@ -481,6 +506,25 @@ def _diff_field_rewrites(show_schema: bool) -> dict[str, Any]:
481
506
  return {} if show_schema else {"jtd_schema": "[NOT SHOWN]"}
482
507
 
483
508
 
509
+ def _show_deprecations(deprecations: list[code_plan.ResourceDeprecation]) -> None:
510
+ if not deprecations:
511
+ return
512
+
513
+ title = "⚠️ NOTICE"
514
+ footer = ""
515
+
516
+ if len(deprecations) > MAX_DEPRECATIONS_TO_SHOW:
517
+ footer = f"And {len(deprecations) - MAX_DEPRECATIONS_TO_SHOW} more...\n"
518
+ deprecations = deprecations[:MAX_DEPRECATIONS_TO_SHOW]
519
+
520
+ print()
521
+ print(f"\033[93m{title}\033[0m") # Make the text yellow
522
+ for i, message in enumerate(sorted(deprecations)):
523
+ print(f"\033[93m{i+1:>2}. {message}\033[0m")
524
+
525
+ print(footer, end="")
526
+
527
+
484
528
  def create_source_schema_reinference(
485
529
  schemas_to_update: list[str], update_all_schemas: bool
486
530
  ) -> SourceSchemaReinference:
@@ -493,6 +537,31 @@ def create_source_schema_reinference(
493
537
  return SourceSchemaReinference(set(source_names) if source_names else None)
494
538
 
495
539
 
540
+ def _create_resource_names(strings: set[str]) -> code_plan.ResourceNames:
541
+ """Construct object from a set of strings.
542
+
543
+ Strings in format <resource_type>:<resource_name> will be converted by
544
+ splitting on `:` and parsing the values.
545
+ """
546
+ resource_names = code_plan.ResourceNames()
547
+
548
+ for target in strings:
549
+ # A resource name can't contain `:` so it's safe to split like this.
550
+ resource_type, name = target.split(":")
551
+
552
+ # User specifies resources in singular (credential) but the class fields
553
+ # throughout the code uses plural so we add an 's'
554
+ resource_type = f"{resource_type}s"
555
+
556
+ if not hasattr(resource_names, resource_type):
557
+ raise ValidioError(f"Invalid resource type '{resource_type}'")
558
+
559
+ v = getattr(resource_names, resource_type)
560
+ v.add(name)
561
+
562
+ return resource_names
563
+
564
+
496
565
  def _print_no_changes() -> None:
497
566
  print("No changes. The configuration is up-to-date!")
498
567
 
@@ -110,9 +110,11 @@ def get(
110
110
  "default_namespace": validio_config.default_namespace,
111
111
  "endpoint": validio_config.endpoint,
112
112
  "access_key": validio_config.access_key,
113
- "access_secret": validio_config._access_secret
114
- if show_secrets
115
- else validio_config.access_secret,
113
+ "access_secret": (
114
+ validio_config._access_secret
115
+ if show_secrets
116
+ else validio_config.access_secret
117
+ ),
116
118
  }
117
119
 
118
120
  if output_format == OutputFormat.JSON:
@@ -180,7 +182,7 @@ async def _test_configuration(config: ValidioConfig) -> str | None:
180
182
 
181
183
  try:
182
184
  # NOTE: Do we need an explicit ping command here?
183
- await vc.get_users()
185
+ await vc.list_users()
184
186
  except UnauthorizedError:
185
187
  return "Unauthorized"
186
188
  except httpx.ConnectError:
@@ -39,7 +39,7 @@ async def get(
39
39
  )
40
40
  ]
41
41
  else:
42
- notification_rules = await vc.get_notification_rules( # type: ignore
42
+ notification_rules = await vc.list_notification_rules( # type: ignore
43
43
  filter=ResourceFilter(namespace_id=get_namespace(namespace, cfg))
44
44
  )
45
45
 
@@ -34,7 +34,7 @@ async def get(
34
34
  )
35
35
  ]
36
36
  else:
37
- users = await vc.get_users()
37
+ users = await vc.list_users()
38
38
 
39
39
  if output_format == OutputFormat.JSON:
40
40
  return output_json(users, identifier)
File without changes