validio-cli 0.19.0__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.
- {validio_cli-0.19.0 → validio_cli-0.20.0}/PKG-INFO +2 -2
- {validio_cli-0.19.0 → validio_cli-0.20.0}/pyproject.toml +2 -2
- {validio_cli-0.19.0 → validio_cli-0.20.0}/validio_cli/bin/entities/channels.py +1 -1
- {validio_cli-0.19.0 → validio_cli-0.20.0}/validio_cli/bin/entities/code.py +71 -2
- {validio_cli-0.19.0 → validio_cli-0.20.0}/validio_cli/bin/entities/config.py +6 -4
- {validio_cli-0.19.0 → validio_cli-0.20.0}/validio_cli/bin/entities/notification_rules.py +1 -1
- {validio_cli-0.19.0 → validio_cli-0.20.0}/validio_cli/bin/entities/users.py +1 -1
- {validio_cli-0.19.0 → validio_cli-0.20.0}/LICENSE +0 -0
- {validio_cli-0.19.0 → validio_cli-0.20.0}/README_PUBLIC.md +0 -0
- {validio_cli-0.19.0 → validio_cli-0.20.0}/validio_cli/__init__.py +0 -0
- {validio_cli-0.19.0 → validio_cli-0.20.0}/validio_cli/bin/entities/credentials.py +0 -0
- {validio_cli-0.19.0 → validio_cli-0.20.0}/validio_cli/bin/entities/dbt.py +0 -0
- {validio_cli-0.19.0 → validio_cli-0.20.0}/validio_cli/bin/entities/incidents.py +0 -0
- {validio_cli-0.19.0 → validio_cli-0.20.0}/validio_cli/bin/entities/metrics.py +0 -0
- {validio_cli-0.19.0 → validio_cli-0.20.0}/validio_cli/bin/entities/recommendations.py +0 -0
- {validio_cli-0.19.0 → validio_cli-0.20.0}/validio_cli/bin/entities/resources.py +0 -0
- {validio_cli-0.19.0 → validio_cli-0.20.0}/validio_cli/bin/entities/segmentations.py +0 -0
- {validio_cli-0.19.0 → validio_cli-0.20.0}/validio_cli/bin/entities/segments.py +0 -0
- {validio_cli-0.19.0 → validio_cli-0.20.0}/validio_cli/bin/entities/sources.py +0 -0
- {validio_cli-0.19.0 → validio_cli-0.20.0}/validio_cli/bin/entities/validators.py +0 -0
- {validio_cli-0.19.0 → validio_cli-0.20.0}/validio_cli/bin/entities/windows.py +0 -0
- {validio_cli-0.19.0 → validio_cli-0.20.0}/validio_cli/bin/main.py +0 -0
- {validio_cli-0.19.0 → validio_cli-0.20.0}/validio_cli/components.py +0 -0
- {validio_cli-0.19.0 → validio_cli-0.20.0}/validio_cli/metadata.py +0 -0
- {validio_cli-0.19.0 → validio_cli-0.20.0}/validio_cli/namespace.py +0 -0
- {validio_cli-0.19.0 → 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.
|
|
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 (
|
|
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.
|
|
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.
|
|
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"
|
|
@@ -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
|
|
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
|
-
|
|
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":
|
|
114
|
-
|
|
115
|
-
|
|
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.
|
|
185
|
+
await vc.list_users()
|
|
184
186
|
except UnauthorizedError:
|
|
185
187
|
return "Unauthorized"
|
|
186
188
|
except httpx.ConnectError:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|