validio-cli 0.17.1__tar.gz → 0.18.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.17.1 → validio_cli-0.18.0}/PKG-INFO +1 -1
  2. {validio_cli-0.17.1 → validio_cli-0.18.0}/pyproject.toml +1 -1
  3. {validio_cli-0.17.1 → validio_cli-0.18.0}/validio_cli/bin/entities/channels.py +3 -3
  4. {validio_cli-0.17.1 → validio_cli-0.18.0}/validio_cli/bin/entities/credentials.py +3 -3
  5. {validio_cli-0.17.1 → validio_cli-0.18.0}/validio_cli/bin/entities/incidents.py +36 -48
  6. {validio_cli-0.17.1 → validio_cli-0.18.0}/validio_cli/bin/entities/notification_rules.py +3 -3
  7. {validio_cli-0.17.1 → validio_cli-0.18.0}/validio_cli/bin/entities/segmentations.py +3 -3
  8. {validio_cli-0.17.1 → validio_cli-0.18.0}/validio_cli/bin/entities/sources.py +4 -4
  9. {validio_cli-0.17.1 → validio_cli-0.18.0}/validio_cli/bin/entities/users.py +1 -1
  10. {validio_cli-0.17.1 → validio_cli-0.18.0}/validio_cli/bin/entities/validators.py +5 -7
  11. {validio_cli-0.17.1 → validio_cli-0.18.0}/validio_cli/bin/entities/windows.py +3 -3
  12. {validio_cli-0.17.1 → validio_cli-0.18.0}/validio_cli/bin/main.py +24 -1
  13. {validio_cli-0.17.1 → validio_cli-0.18.0}/LICENSE +0 -0
  14. {validio_cli-0.17.1 → validio_cli-0.18.0}/README_PUBLIC.md +0 -0
  15. {validio_cli-0.17.1 → validio_cli-0.18.0}/validio_cli/__init__.py +0 -0
  16. {validio_cli-0.17.1 → validio_cli-0.18.0}/validio_cli/bin/entities/code.py +0 -0
  17. {validio_cli-0.17.1 → validio_cli-0.18.0}/validio_cli/bin/entities/config.py +0 -0
  18. {validio_cli-0.17.1 → validio_cli-0.18.0}/validio_cli/bin/entities/dbt.py +0 -0
  19. {validio_cli-0.17.1 → validio_cli-0.18.0}/validio_cli/bin/entities/metrics.py +0 -0
  20. {validio_cli-0.17.1 → validio_cli-0.18.0}/validio_cli/bin/entities/recommendations.py +0 -0
  21. {validio_cli-0.17.1 → validio_cli-0.18.0}/validio_cli/bin/entities/resources.py +0 -0
  22. {validio_cli-0.17.1 → validio_cli-0.18.0}/validio_cli/bin/entities/segments.py +0 -0
  23. {validio_cli-0.17.1 → validio_cli-0.18.0}/validio_cli/components.py +0 -0
  24. {validio_cli-0.17.1 → validio_cli-0.18.0}/validio_cli/metadata.py +0 -0
  25. {validio_cli-0.17.1 → validio_cli-0.18.0}/validio_cli/namespace.py +0 -0
  26. {validio_cli-0.17.1 → validio_cli-0.18.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.17.1
3
+ Version: 0.18.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
@@ -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.17.1"
6
+ version = "0.18.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"
@@ -35,12 +35,12 @@ async def get(
35
35
  if identifier is not None and not identifier.startswith("CNL_"):
36
36
  channels = [
37
37
  await vc.get_channel_by_resource_name(
38
- resource_name=identifier, resource_namespace=ns
38
+ resource_name=identifier, namespace_id=ns
39
39
  )
40
40
  ]
41
41
  else:
42
42
  channels = await vc.get_channels( # type: ignore
43
- filter=ResourceFilter(resource_namespace=ns)
43
+ filter=ResourceFilter(namespace_id=ns)
44
44
  )
45
45
 
46
46
  # TODO(UI-2311): Fully support list/get/get_by_resource_name
@@ -82,7 +82,7 @@ async def get_channel_id(
82
82
 
83
83
  resource = await vc.get_channel_by_resource_name(
84
84
  resource_name=identifier,
85
- resource_namespace=get_namespace(namespace, cfg),
85
+ namespace_id=get_namespace(namespace, cfg),
86
86
  )
87
87
 
88
88
  if resource is None:
@@ -34,12 +34,12 @@ async def get(
34
34
  credentials = [
35
35
  await vc.get_credential_by_resource_name(
36
36
  resource_name=identifier,
37
- resource_namespace=namespace,
37
+ namespace_id=namespace,
38
38
  )
39
39
  ]
40
40
  else:
41
41
  credentials = await vc.list_credentials( # type: ignore
42
- filter=ResourceFilter(resource_namespace=get_namespace(namespace, cfg))
42
+ filter=ResourceFilter(namespace_id=get_namespace(namespace, cfg))
43
43
  )
44
44
 
45
45
  # TODO(UI-2311): Fully support list/get/get_by_resource_name
@@ -81,7 +81,7 @@ async def get_credential_id(
81
81
  (
82
82
  credential.id
83
83
  for credential in await vc.list_credentials(
84
- filter=ResourceFilter(resource_namespace=get_namespace(namespace, cfg))
84
+ filter=ResourceFilter(namespace_id=get_namespace(namespace, cfg))
85
85
  )
86
86
  if credential.resource_name == identifier
87
87
  ),
@@ -2,11 +2,6 @@ from datetime import datetime, timedelta
2
2
  from typing import Any
3
3
 
4
4
  import typer
5
- from validio_sdk import ValidioError
6
- from validio_sdk.graphql_client.get_source_incidents import GetSourceIncidentsSource
7
- from validio_sdk.graphql_client.get_validator_incidents import (
8
- GetValidatorIncidentsValidator,
9
- )
10
5
  from validio_sdk.graphql_client.input_types import TimeRangeInput
11
6
 
12
7
  from validio_cli import (
@@ -21,7 +16,7 @@ from validio_cli import (
21
16
  output_json,
22
17
  output_text,
23
18
  )
24
- from validio_cli.bin.entities import sources, validators
19
+ from validio_cli.bin.entities import validators
25
20
 
26
21
  app = AsyncTyper(help="Incidents from validators")
27
22
 
@@ -36,8 +31,6 @@ You can list incidents in different ways:
36
31
 
37
32
  * Listing all incidents
38
33
 
39
- * Listing all source incidents for a specific source with --source
40
-
41
34
  * Listing all incidents for a specific validator with --validator
42
35
 
43
36
  * Listing all incidents for a specific segment with --segment
@@ -58,9 +51,8 @@ async def get(
58
51
  (datetime.utcnow() - timedelta(hours=1)),
59
52
  help="The incident ended after this timestamp",
60
53
  ),
61
- validator: str = typer.Option(None, help="Validator to fetch incidents for"),
54
+ validator: str = typer.Option(..., help="Validator to fetch incidents for"),
62
55
  segment: str = typer.Option(None, help="Segment to fetch incidents for"),
63
- source: str = typer.Option(None, help="Source to fetch incidents for"),
64
56
  ) -> None:
65
57
  vc, cfg = await get_client_and_config(config_dir)
66
58
 
@@ -69,36 +61,16 @@ async def get(
69
61
  if validator_id is None:
70
62
  return None
71
63
 
72
- if source is not None:
73
- source_id = await sources.get_source_id(vc, cfg, source, namespace)
74
- if source_id is None:
75
- return None
76
-
77
64
  # TODO(UI-2006): These should all support namespace
78
65
 
79
- incidents: None | GetValidatorIncidentsValidator | GetSourceIncidentsSource = None
80
-
81
- if validator:
82
- incidents = await vc.get_validator_incidents(
83
- id=validator_id,
84
- range=TimeRangeInput(
85
- start=ended_after,
86
- end=ended_before,
87
- ),
88
- segment_id=segment,
89
- )
90
- elif source:
91
- incidents = await vc.get_source_incidents(
92
- id=source_id,
93
- range=TimeRangeInput(
94
- start=ended_after,
95
- end=ended_before,
96
- ),
97
- )
98
- else:
99
- raise ValidioError(
100
- "You need to specify one of --validator and/or --segment or --source"
101
- )
66
+ incidents = await vc.get_validator_incidents(
67
+ id=validator_id,
68
+ range=TimeRangeInput(
69
+ start=ended_after,
70
+ end=ended_before,
71
+ ),
72
+ segment_id=segment,
73
+ )
102
74
 
103
75
  if not incidents:
104
76
  return output_text(None, {})
@@ -109,20 +81,23 @@ async def get(
109
81
  return output_text(
110
82
  incidents.incidents,
111
83
  fields={
112
- "operator": OutputSettings(
113
- attribute_name="metric",
114
- reformat=calculate_operator,
84
+ "validator": OutputSettings(
85
+ pass_full_object=True,
86
+ reformat=lambda _: incidents.typename__,
115
87
  ),
116
88
  "bound": OutputSettings(
117
- attribute_name="metric",
118
- reformat=calculate_bound,
119
- ),
120
- "value": OutputSettings(
121
- attribute_name="metric",
122
- reformat=lambda x: x.value,
89
+ pass_full_object=True,
90
+ reformat=lambda x: (
91
+ f"{format_number(x.lower_bound)} - "
92
+ f"{format_number(x.upper_bound)}"
93
+ ),
123
94
  ),
95
+ "value": OutputSettings(reformat=format_number),
96
+ "deviation": OutputSettings(reformat=format_number),
97
+ "severity": None,
98
+ "status": None,
124
99
  "age": OutputSettings(
125
- attribute_name="metric",
100
+ pass_full_object=True,
126
101
  reformat=lambda x: _format_relative_time(x.end_time),
127
102
  ),
128
103
  },
@@ -151,5 +126,18 @@ def calculate_bound(item: Any) -> str:
151
126
  return bound
152
127
 
153
128
 
129
+ def format_number(item: Any) -> str:
130
+ if item % 1 == 0:
131
+ return str(item)
132
+ if (item * 10) % 1 == 0:
133
+ return f"{item:.1f}"
134
+ if (item * 100) % 1 == 0:
135
+ return f"{item:.2f}"
136
+ if (item * 1000) % 1 == 0:
137
+ return f"{item:.3f}"
138
+
139
+ return f"{item:.3f}..."
140
+
141
+
154
142
  if __name__ == "__main__":
155
143
  typer.run(app())
@@ -35,12 +35,12 @@ async def get(
35
35
  notification_rules = [
36
36
  await vc.get_notification_rule_by_resource_name(
37
37
  resource_name=identifier,
38
- resource_namespace=get_namespace(namespace, cfg),
38
+ namespace_id=get_namespace(namespace, cfg),
39
39
  )
40
40
  ]
41
41
  else:
42
42
  notification_rules = await vc.get_notification_rules( # type: ignore
43
- filter=ResourceFilter(resource_namespace=get_namespace(namespace, cfg))
43
+ filter=ResourceFilter(namespace_id=get_namespace(namespace, cfg))
44
44
  )
45
45
 
46
46
  # TODO(UI-2311): Fully support list/get/get_by_resource_name
@@ -85,7 +85,7 @@ async def get_notification_rule_id(
85
85
 
86
86
  resource = await vc.get_notification_rule_by_resource_name(
87
87
  resource_name=identifier,
88
- resource_namespace=get_namespace(namespace, cfg),
88
+ namespace_id=get_namespace(namespace, cfg),
89
89
  )
90
90
 
91
91
  if resource is None:
@@ -43,12 +43,12 @@ async def get(
43
43
  segmentations = [
44
44
  await vc.get_segmentation_by_resource_name(
45
45
  resource_name=identifier,
46
- resource_namespace=get_namespace(namespace, cfg),
46
+ namespace_id=get_namespace(namespace, cfg),
47
47
  )
48
48
  ]
49
49
  else:
50
50
  segmentations = await vc.list_segmentations(
51
- filter=ResourceFilter(resource_namespace=get_namespace(namespace, cfg))
51
+ filter=ResourceFilter(namespace_id=get_namespace(namespace, cfg))
52
52
  )
53
53
 
54
54
  segmentations = [
@@ -91,7 +91,7 @@ async def get_segmentation_id(
91
91
 
92
92
  resource = await vc.get_segmentation_by_resource_name(
93
93
  resource_name=identifier,
94
- resource_namespace=get_namespace(namespace, cfg),
94
+ namespace_id=get_namespace(namespace, cfg),
95
95
  )
96
96
 
97
97
  if resource is None:
@@ -81,12 +81,12 @@ async def get(
81
81
  sources = [
82
82
  await vc.get_source_by_resource_name(
83
83
  resource_name=identifier,
84
- resource_namespace=get_namespace(namespace, cfg),
84
+ namespace_id=get_namespace(namespace, cfg),
85
85
  )
86
86
  ]
87
87
  else:
88
88
  sources = await vc.list_sources(
89
- filter=ResourceFilter(resource_namespace=get_namespace(namespace, cfg))
89
+ filter=ResourceFilter(namespace_id=get_namespace(namespace, cfg))
90
90
  )
91
91
 
92
92
  sources = [
@@ -231,7 +231,7 @@ async def _interactive(config_dir: str, filename: Path, namespace: str) -> None:
231
231
  vc, cfg = await get_client_and_config(config_dir)
232
232
 
233
233
  credentials = await vc.list_credentials(
234
- filter=ResourceFilter(resource_namespace=get_namespace(namespace, cfg))
234
+ filter=ResourceFilter(namespace_id=get_namespace(namespace, cfg))
235
235
  )
236
236
 
237
237
  if len(credentials) == 0:
@@ -1173,7 +1173,7 @@ async def get_source_id(
1173
1173
 
1174
1174
  resource = await vc.get_source_by_resource_name(
1175
1175
  resource_name=identifier,
1176
- resource_namespace=get_namespace(namespace, cfg),
1176
+ namespace_id=get_namespace(namespace, cfg),
1177
1177
  )
1178
1178
 
1179
1179
  if resource is None:
@@ -30,7 +30,7 @@ async def get(
30
30
  users = [
31
31
  await vc.get_user_by_resource_name(
32
32
  resource_name=identifier,
33
- resource_namespace=get_namespace(namespace, cfg),
33
+ namespace_id=get_namespace(namespace, cfg),
34
34
  )
35
35
  ]
36
36
  else:
@@ -49,25 +49,23 @@ async def get(
49
49
  validators.append(
50
50
  await vc.get_validator_by_resource_name(
51
51
  resource_name=identifier,
52
- resource_namespace=get_namespace(namespace, cfg),
52
+ namespace_id=get_namespace(namespace, cfg),
53
53
  )
54
54
  )
55
55
  elif source is None or not source.startswith("SRC_"):
56
56
  for s in await vc.list_sources(
57
- filter=ResourceFilter(resource_namespace=get_namespace(namespace, cfg))
57
+ filter=ResourceFilter(namespace_id=get_namespace(namespace, cfg))
58
58
  ):
59
59
  validators.extend(
60
60
  await vc.list_validators(
61
61
  id=s.id,
62
- filter=ResourceFilter(
63
- resource_namespace=get_namespace(namespace, cfg)
64
- ),
62
+ filter=ResourceFilter(namespace_id=get_namespace(namespace, cfg)),
65
63
  ),
66
64
  )
67
65
  else:
68
66
  validators = await vc.list_validators(
69
67
  id=source,
70
- filter=ResourceFilter(resource_namespace=get_namespace(namespace, cfg)),
68
+ filter=ResourceFilter(namespace_id=get_namespace(namespace, cfg)),
71
69
  )
72
70
 
73
71
  validators = [
@@ -113,7 +111,7 @@ async def get_validator_id(
113
111
 
114
112
  resource = await vc.get_validator_by_resource_name(
115
113
  resource_name=identifier,
116
- resource_namespace=get_namespace(namespace, cfg),
114
+ namespace_id=get_namespace(namespace, cfg),
117
115
  )
118
116
 
119
117
  if resource is None:
@@ -37,12 +37,12 @@ async def get(
37
37
  windows = [
38
38
  await vc.get_window_by_resource_name(
39
39
  resource_name=identifier,
40
- resource_namespace=get_namespace(namespace, cfg),
40
+ namespace_id=get_namespace(namespace, cfg),
41
41
  )
42
42
  ]
43
43
  else:
44
44
  windows = await vc.list_windows( # type: ignore
45
- filter=ResourceFilter(resource_namespace=get_namespace(namespace, cfg))
45
+ filter=ResourceFilter(namespace_id=get_namespace(namespace, cfg))
46
46
  )
47
47
 
48
48
  windows = [
@@ -94,7 +94,7 @@ async def get_window_id(
94
94
 
95
95
  resource = await vc.get_window_by_resource_name(
96
96
  resource_name=identifier,
97
- resource_namespace=get_namespace(namespace, cfg),
97
+ namespace_id=get_namespace(namespace, cfg),
98
98
  )
99
99
 
100
100
  if resource is None:
@@ -8,6 +8,13 @@ import validio_sdk.metadata
8
8
  from tabulate import tabulate
9
9
  from validio_sdk import ValidioError
10
10
  from validio_sdk.config import Config
11
+ from validio_sdk.graphql_client.exceptions import (
12
+ GraphQLClientGraphQLError,
13
+ GraphQLClientGraphQLMultiError,
14
+ GraphQLClientHttpError,
15
+ GraphQLClientInvalidMessageFormat,
16
+ GraphQLClientInvalidResponseError,
17
+ )
11
18
 
12
19
  import validio_cli.metadata
13
20
  from validio_cli.bin.entities import (
@@ -170,9 +177,25 @@ def main() -> None:
170
177
 
171
178
  # ValidioErrors are thrown by us and should not require the stack trace
172
179
  # to tell what went wrong.
173
- except ValidioError as e:
180
+ # GraphQL errors doesn't contain any valuable information in the trace, we
181
+ # only want to print the error message.
182
+ except (
183
+ ValidioError,
184
+ GraphQLClientGraphQLError,
185
+ GraphQLClientGraphQLMultiError,
186
+ GraphQLClientHttpError,
187
+ GraphQLClientInvalidMessageFormat,
188
+ GraphQLClientInvalidResponseError,
189
+ ) as e:
174
190
  print(f"Something went wrong: {e}")
175
191
 
192
+ # For the other errors check if they're known children.
193
+ except Exception as e:
194
+ if issubclass(type(e), ValidioError):
195
+ print(f"Something went wrong: {e}")
196
+ else:
197
+ raise e
198
+
176
199
  sys.exit(exit_code)
177
200
 
178
201
 
File without changes