cacholong-cloud-cli 0.3.4__tar.gz → 1.1.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 (100) hide show
  1. {cacholong_cloud_cli-0.3.4 → cacholong_cloud_cli-1.1.0}/PKG-INFO +3 -2
  2. {cacholong_cloud_cli-0.3.4 → cacholong_cloud_cli-1.1.0}/cacholong_cli/AsyncTyper.py +6 -3
  3. {cacholong_cloud_cli-0.3.4 → cacholong_cloud_cli-1.1.0}/cacholong_cli/cli.py +14 -1
  4. cacholong_cloud_cli-1.1.0/cacholong_cli/commands/accounts.py +431 -0
  5. cacholong_cloud_cli-1.1.0/cacholong_cli/commands/addresses.py +503 -0
  6. cacholong_cloud_cli-1.1.0/cacholong_cli/commands/companies.py +362 -0
  7. cacholong_cloud_cli-1.1.0/cacholong_cli/commands/dns_records.py +414 -0
  8. cacholong_cloud_cli-1.1.0/cacholong_cli/commands/dns_templates.py +296 -0
  9. cacholong_cloud_cli-1.1.0/cacholong_cli/commands/dns_zones.py +400 -0
  10. cacholong_cloud_cli-1.1.0/cacholong_cli/commands/mail_address_aliases.py +362 -0
  11. cacholong_cloud_cli-1.1.0/cacholong_cli/commands/mail_addresses.py +666 -0
  12. cacholong_cloud_cli-1.1.0/cacholong_cli/commands/mail_domains.py +579 -0
  13. cacholong_cloud_cli-1.1.0/cacholong_cli/commands/mail_forwards.py +341 -0
  14. cacholong_cloud_cli-1.1.0/cacholong_cli/commands/products.py +385 -0
  15. cacholong_cloud_cli-1.1.0/cacholong_cli/commands/purchases.py +522 -0
  16. cacholong_cloud_cli-1.1.0/cacholong_cli/commands/users.py +204 -0
  17. {cacholong_cloud_cli-0.3.4 → cacholong_cloud_cli-1.1.0}/cacholong_cli/common.py +31 -17
  18. {cacholong_cloud_cli-0.3.4 → cacholong_cloud_cli-1.1.0}/cacholong_cli/connection.py +4 -1
  19. cacholong_cloud_cli-1.1.0/cacholong_sdk/__init__.py +72 -0
  20. cacholong_cloud_cli-1.1.0/cacholong_sdk/account_base.py +15 -0
  21. cacholong_cloud_cli-1.1.0/cacholong_sdk/account_show.py +15 -0
  22. cacholong_cloud_cli-1.1.0/cacholong_sdk/address_base.py +15 -0
  23. cacholong_cloud_cli-1.1.0/cacholong_sdk/address_create_with_company.py +17 -0
  24. cacholong_cloud_cli-1.1.0/cacholong_sdk/address_create_with_user.py +17 -0
  25. cacholong_cloud_cli-1.1.0/cacholong_sdk/address_show.py +15 -0
  26. cacholong_cloud_cli-1.1.0/cacholong_sdk/address_update.py +15 -0
  27. cacholong_cloud_cli-1.1.0/cacholong_sdk/api_schema.py +752 -0
  28. {cacholong_cloud_cli-0.3.4 → cacholong_cloud_cli-1.1.0}/cacholong_sdk/common.py +76 -5
  29. cacholong_cloud_cli-1.1.0/cacholong_sdk/company_base.py +15 -0
  30. cacholong_cloud_cli-1.1.0/cacholong_sdk/company_show.py +15 -0
  31. cacholong_cloud_cli-1.1.0/cacholong_sdk/company_update.py +15 -0
  32. cacholong_cloud_cli-1.1.0/cacholong_sdk/dns_record_base.py +15 -0
  33. cacholong_cloud_cli-1.1.0/cacholong_sdk/dns_record_create_with_template.py +17 -0
  34. cacholong_cloud_cli-1.1.0/cacholong_sdk/dns_record_create_with_zone.py +17 -0
  35. cacholong_cloud_cli-1.1.0/cacholong_sdk/dns_record_show.py +15 -0
  36. cacholong_cloud_cli-1.1.0/cacholong_sdk/dns_record_update.py +15 -0
  37. cacholong_cloud_cli-1.1.0/cacholong_sdk/dns_template_base.py +15 -0
  38. cacholong_cloud_cli-1.1.0/cacholong_sdk/dns_template_create.py +15 -0
  39. cacholong_cloud_cli-1.1.0/cacholong_sdk/dns_template_show.py +15 -0
  40. cacholong_cloud_cli-1.1.0/cacholong_sdk/dns_template_update.py +15 -0
  41. cacholong_cloud_cli-1.1.0/cacholong_sdk/dns_zone_base.py +15 -0
  42. cacholong_cloud_cli-1.1.0/cacholong_sdk/dns_zone_create.py +15 -0
  43. cacholong_cloud_cli-1.1.0/cacholong_sdk/dns_zone_show.py +15 -0
  44. cacholong_cloud_cli-1.1.0/cacholong_sdk/dns_zone_update.py +15 -0
  45. cacholong_cloud_cli-1.1.0/cacholong_sdk/mail_address_alias_base.py +15 -0
  46. cacholong_cloud_cli-1.1.0/cacholong_sdk/mail_address_alias_create.py +15 -0
  47. cacholong_cloud_cli-1.1.0/cacholong_sdk/mail_address_alias_show.py +15 -0
  48. cacholong_cloud_cli-1.1.0/cacholong_sdk/mail_address_alias_update.py +15 -0
  49. cacholong_cloud_cli-1.1.0/cacholong_sdk/mail_address_base.py +15 -0
  50. cacholong_cloud_cli-1.1.0/cacholong_sdk/mail_address_create.py +15 -0
  51. cacholong_cloud_cli-1.1.0/cacholong_sdk/mail_address_show.py +15 -0
  52. cacholong_cloud_cli-1.1.0/cacholong_sdk/mail_address_update.py +15 -0
  53. cacholong_cloud_cli-1.1.0/cacholong_sdk/mail_domain_base.py +15 -0
  54. cacholong_cloud_cli-1.1.0/cacholong_sdk/mail_domain_show.py +15 -0
  55. cacholong_cloud_cli-1.1.0/cacholong_sdk/mail_forward_base.py +15 -0
  56. cacholong_cloud_cli-1.1.0/cacholong_sdk/mail_forward_create.py +15 -0
  57. cacholong_cloud_cli-1.1.0/cacholong_sdk/mail_forward_show.py +15 -0
  58. cacholong_cloud_cli-1.1.0/cacholong_sdk/mail_forward_update.py +15 -0
  59. cacholong_cloud_cli-1.1.0/cacholong_sdk/product_base.py +15 -0
  60. cacholong_cloud_cli-1.1.0/cacholong_sdk/product_show.py +15 -0
  61. cacholong_cloud_cli-1.1.0/cacholong_sdk/purchase_base.py +15 -0
  62. cacholong_cloud_cli-1.1.0/cacholong_sdk/purchase_show.py +15 -0
  63. cacholong_cloud_cli-1.1.0/cacholong_sdk/service_mail_base.py +15 -0
  64. cacholong_cloud_cli-1.1.0/cacholong_sdk/service_mail_show.py +15 -0
  65. cacholong_cloud_cli-1.1.0/cacholong_sdk/user_base.py +15 -0
  66. cacholong_cloud_cli-1.1.0/cacholong_sdk/user_role_base.py +15 -0
  67. cacholong_cloud_cli-1.1.0/cacholong_sdk/user_role_show.py +15 -0
  68. cacholong_cloud_cli-1.1.0/cacholong_sdk/user_show.py +15 -0
  69. {cacholong_cloud_cli-0.3.4 → cacholong_cloud_cli-1.1.0}/pyproject.toml +2 -1
  70. cacholong_cloud_cli-0.3.4/cacholong_cli/commands/accounts.py +0 -105
  71. cacholong_cloud_cli-0.3.4/cacholong_cli/commands/addresses.py +0 -280
  72. cacholong_cloud_cli-0.3.4/cacholong_cli/commands/companies.py +0 -100
  73. cacholong_cloud_cli-0.3.4/cacholong_cli/commands/dns_records.py +0 -275
  74. cacholong_cloud_cli-0.3.4/cacholong_cli/commands/dns_templates.py +0 -141
  75. cacholong_cloud_cli-0.3.4/cacholong_cli/commands/dns_zones.py +0 -277
  76. cacholong_cloud_cli-0.3.4/cacholong_cli/commands/products.py +0 -121
  77. cacholong_cloud_cli-0.3.4/cacholong_cli/commands/purchases.py +0 -127
  78. cacholong_cloud_cli-0.3.4/cacholong_sdk/__init__.py +0 -18
  79. cacholong_cloud_cli-0.3.4/cacholong_sdk/account.py +0 -14
  80. cacholong_cloud_cli-0.3.4/cacholong_sdk/address.py +0 -14
  81. cacholong_cloud_cli-0.3.4/cacholong_sdk/api_schema.py +0 -124
  82. cacholong_cloud_cli-0.3.4/cacholong_sdk/company.py +0 -14
  83. cacholong_cloud_cli-0.3.4/cacholong_sdk/dns_record.py +0 -14
  84. cacholong_cloud_cli-0.3.4/cacholong_sdk/dns_template.py +0 -14
  85. cacholong_cloud_cli-0.3.4/cacholong_sdk/dns_zone.py +0 -14
  86. cacholong_cloud_cli-0.3.4/cacholong_sdk/product.py +0 -14
  87. cacholong_cloud_cli-0.3.4/cacholong_sdk/purchase.py +0 -14
  88. {cacholong_cloud_cli-0.3.4 → cacholong_cloud_cli-1.1.0}/README.md +0 -0
  89. {cacholong_cloud_cli-0.3.4 → cacholong_cloud_cli-1.1.0}/cacholong_cli/__init__.py +0 -0
  90. {cacholong_cloud_cli-0.3.4 → cacholong_cloud_cli-1.1.0}/cacholong_sdk/connection.py +0 -0
  91. {cacholong_cloud_cli-0.3.4 → cacholong_cloud_cli-1.1.0}/cacholong_sdk/exception.py +0 -0
  92. {cacholong_cloud_cli-0.3.4 → cacholong_cloud_cli-1.1.0}/jsonapi-client/src/jsonapi_client/__init__.py +0 -0
  93. {cacholong_cloud_cli-0.3.4 → cacholong_cloud_cli-1.1.0}/jsonapi-client/src/jsonapi_client/common.py +0 -0
  94. {cacholong_cloud_cli-0.3.4 → cacholong_cloud_cli-1.1.0}/jsonapi-client/src/jsonapi_client/document.py +0 -0
  95. {cacholong_cloud_cli-0.3.4 → cacholong_cloud_cli-1.1.0}/jsonapi-client/src/jsonapi_client/exceptions.py +0 -0
  96. {cacholong_cloud_cli-0.3.4 → cacholong_cloud_cli-1.1.0}/jsonapi-client/src/jsonapi_client/filter.py +0 -0
  97. {cacholong_cloud_cli-0.3.4 → cacholong_cloud_cli-1.1.0}/jsonapi-client/src/jsonapi_client/objects.py +0 -0
  98. {cacholong_cloud_cli-0.3.4 → cacholong_cloud_cli-1.1.0}/jsonapi-client/src/jsonapi_client/relationships.py +0 -0
  99. {cacholong_cloud_cli-0.3.4 → cacholong_cloud_cli-1.1.0}/jsonapi-client/src/jsonapi_client/resourceobject.py +0 -0
  100. {cacholong_cloud_cli-0.3.4 → cacholong_cloud_cli-1.1.0}/jsonapi-client/src/jsonapi_client/session.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: cacholong-cloud-cli
3
- Version: 0.3.4
3
+ Version: 1.1.0
4
4
  Summary: Cacholong CLI, manage cloud environments at Cacholong!
5
5
  License: MIT
6
6
  Author: Matthijs Möhlmann
@@ -11,6 +11,7 @@ Classifier: Programming Language :: Python :: 3
11
11
  Classifier: Programming Language :: Python :: 3.11
12
12
  Classifier: Programming Language :: Python :: 3.12
13
13
  Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Programming Language :: Python :: 3.14
14
15
  Requires-Dist: aiodns (>=3.5.0,<4.0.0)
15
16
  Requires-Dist: aiofiles (>=23.2.1,<24.0.0)
16
17
  Requires-Dist: aiohttp (>=3.0)
@@ -1,14 +1,17 @@
1
1
  from asyncio import run
2
2
  from functools import wraps
3
+ from typing import Callable, Any
3
4
 
4
5
  import typer
5
6
 
6
7
 
7
8
  class AsyncTyper(typer.Typer):
8
- def async_command(self, *args, **kwargs):
9
- def decorator(async_func):
9
+ def async_command(
10
+ self, *args: Any, **kwargs: Any
11
+ ) -> Callable[[Callable], Callable]:
12
+ def decorator(async_func: Callable) -> Callable:
10
13
  @wraps(async_func)
11
- def sync_func(*_args, **_kwargs):
14
+ def sync_func(*_args: Any, **_kwargs: Any) -> Any:
12
15
  return run(async_func(*_args, **_kwargs))
13
16
 
14
17
  self.command(*args, **kwargs)(sync_func)
@@ -11,13 +11,17 @@ from cacholong_cli.commands import (
11
11
  dns_records,
12
12
  dns_templates,
13
13
  dns_zones,
14
+ mail_addresses,
15
+ mail_address_aliases,
16
+ mail_domains,
17
+ mail_forwards,
14
18
  products,
15
19
  purchases,
20
+ users,
16
21
  )
17
22
  from cacholong_cli.common import OutputFormat
18
23
  from xdg import BaseDirectory
19
24
 
20
-
21
25
  # Version of our CLI
22
26
  __version__ = importlib.metadata.version("cacholong-cloud-cli")
23
27
 
@@ -44,8 +48,17 @@ app.add_typer(companies.app, name="companies", help="Manage companies")
44
48
  app.add_typer(dns_records.app, name="dns-records", help="Manage DNS records")
45
49
  app.add_typer(dns_templates.app, name="dns-templates", help="Manage DNS templates")
46
50
  app.add_typer(dns_zones.app, name="dns-zones", help="Manage DNS zones")
51
+ app.add_typer(mail_addresses.app, name="mail-addresses", help="Manage mail addresses")
52
+ app.add_typer(
53
+ mail_address_aliases.app,
54
+ name="mail-address-aliases",
55
+ help="Manage mail address aliases",
56
+ )
57
+ app.add_typer(mail_domains.app, name="mail-domains", help="Manage mail domains")
58
+ app.add_typer(mail_forwards.app, name="mail-forwards", help="Manage mail forwards")
47
59
  app.add_typer(products.app, name="products", help="Manage products")
48
60
  app.add_typer(purchases.app, name="purchases", help="Manage purchases")
61
+ app.add_typer(users.app, name="users", help="")
49
62
 
50
63
 
51
64
  # Handle version
@@ -0,0 +1,431 @@
1
+ import asyncio
2
+ import typer
3
+ from typing import List, Optional, Dict, Any, Union, Type
4
+ from typing_extensions import Annotated
5
+ from rich.table import Column
6
+ from uuid import UUID
7
+ from datetime import datetime, date, timezone
8
+ from cacholong_cli.AsyncTyper import AsyncTyper
9
+ from cacholong_cli.common import (
10
+ list_resources,
11
+ list_relation_resources,
12
+ show_resource,
13
+ print_document_error,
14
+ TableDef,
15
+ )
16
+ from cacholong_cli.connection import Connection
17
+ from cacholong_sdk import Filter, Inclusion, DocumentError, ResourceTuple
18
+ from cacholong_sdk import AccountBase, AccountBaseModel
19
+
20
+ from cacholong_sdk.api_schema import api_schema
21
+
22
+ # Create typer object
23
+ app = AsyncTyper()
24
+
25
+
26
+ @app.async_command(help="Get accounts")
27
+ async def list(
28
+ ctx: typer.Context,
29
+ name: Annotated[Optional[str], typer.Option(help="The unique account name")] = None,
30
+ description: Annotated[
31
+ Optional[str], typer.Option(help="Optional description of the account")
32
+ ] = None,
33
+ account_type: Annotated[
34
+ Optional[str], typer.Option(help="The account type")
35
+ ] = None,
36
+ account_account_id: Annotated[
37
+ Optional[str], typer.Option(help="Parent account ID")
38
+ ] = None,
39
+ account_account_relation: Annotated[
40
+ Optional[str], typer.Option(help="Parent account relationship type")
41
+ ] = None,
42
+ company: Annotated[
43
+ Optional[UUID], typer.Option(help="The company associated with this account")
44
+ ] = None,
45
+ created_at: Annotated[
46
+ Optional[datetime],
47
+ typer.Option(help="Timestamp when the account was created (exact match)"),
48
+ ] = None,
49
+ created_at_gte: Annotated[
50
+ Optional[datetime],
51
+ typer.Option(
52
+ help="Timestamp when the account was created (greater than or equal)"
53
+ ),
54
+ ] = None,
55
+ created_at_lte: Annotated[
56
+ Optional[datetime],
57
+ typer.Option(
58
+ help="Timestamp when the account was created (less than or equal)"
59
+ ),
60
+ ] = None,
61
+ created_at_gt: Annotated[
62
+ Optional[datetime],
63
+ typer.Option(help="Timestamp when the account was created (greater than)"),
64
+ ] = None,
65
+ created_at_lt: Annotated[
66
+ Optional[datetime],
67
+ typer.Option(help="Timestamp when the account was created (less than)"),
68
+ ] = None,
69
+ updated_at: Annotated[
70
+ Optional[datetime],
71
+ typer.Option(help="Timestamp when the account was last updated (exact match)"),
72
+ ] = None,
73
+ updated_at_gte: Annotated[
74
+ Optional[datetime],
75
+ typer.Option(
76
+ help="Timestamp when the account was last updated (greater than or equal)"
77
+ ),
78
+ ] = None,
79
+ updated_at_lte: Annotated[
80
+ Optional[datetime],
81
+ typer.Option(
82
+ help="Timestamp when the account was last updated (less than or equal)"
83
+ ),
84
+ ] = None,
85
+ updated_at_gt: Annotated[
86
+ Optional[datetime],
87
+ typer.Option(help="Timestamp when the account was last updated (greater than)"),
88
+ ] = None,
89
+ updated_at_lt: Annotated[
90
+ Optional[datetime],
91
+ typer.Option(help="Timestamp when the account was last updated (less than)"),
92
+ ] = None,
93
+ ):
94
+
95
+ # Build modifier
96
+ modifier = []
97
+
98
+ if name is not None:
99
+ modifier.append(Filter(name=name))
100
+
101
+ if description is not None:
102
+ modifier.append(Filter(description=description))
103
+
104
+ if account_type is not None:
105
+ modifier.append(Filter(query_str="filter[account_type]=" + str(account_type)))
106
+
107
+ if account_account_id is not None:
108
+ modifier.append(
109
+ Filter(query_str="filter[account_account_id]=" + str(account_account_id))
110
+ )
111
+
112
+ if account_account_relation is not None:
113
+ modifier.append(
114
+ Filter(
115
+ query_str="filter[account_account_relation]="
116
+ + str(account_account_relation)
117
+ )
118
+ )
119
+
120
+ if company is not None:
121
+ modifier.append(Filter(company=str(company)))
122
+
123
+ if created_at is not None:
124
+ modifier.append(
125
+ Filter(
126
+ query_str="filter[created_at]="
127
+ + created_at.astimezone(timezone.utc)
128
+ .replace(tzinfo=None)
129
+ .isoformat(timespec="milliseconds")
130
+ + "Z"
131
+ )
132
+ )
133
+ if created_at_gte is not None:
134
+ modifier.append(
135
+ Filter(
136
+ query_str="filter[created_at_gte]="
137
+ + created_at_gte.astimezone(timezone.utc)
138
+ .replace(tzinfo=None)
139
+ .isoformat(timespec="milliseconds")
140
+ + "Z"
141
+ )
142
+ )
143
+ if created_at_lte is not None:
144
+ modifier.append(
145
+ Filter(
146
+ query_str="filter[created_at_lte]="
147
+ + created_at_lte.astimezone(timezone.utc)
148
+ .replace(tzinfo=None)
149
+ .isoformat(timespec="milliseconds")
150
+ + "Z"
151
+ )
152
+ )
153
+ if created_at_gt is not None:
154
+ modifier.append(
155
+ Filter(
156
+ query_str="filter[created_at_gt]="
157
+ + created_at_gt.astimezone(timezone.utc)
158
+ .replace(tzinfo=None)
159
+ .isoformat(timespec="milliseconds")
160
+ + "Z"
161
+ )
162
+ )
163
+ if created_at_lt is not None:
164
+ modifier.append(
165
+ Filter(
166
+ query_str="filter[created_at_lt]="
167
+ + created_at_lt.astimezone(timezone.utc)
168
+ .replace(tzinfo=None)
169
+ .isoformat(timespec="milliseconds")
170
+ + "Z"
171
+ )
172
+ )
173
+
174
+ if updated_at is not None:
175
+ modifier.append(
176
+ Filter(
177
+ query_str="filter[updated_at]="
178
+ + updated_at.astimezone(timezone.utc)
179
+ .replace(tzinfo=None)
180
+ .isoformat(timespec="milliseconds")
181
+ + "Z"
182
+ )
183
+ )
184
+ if updated_at_gte is not None:
185
+ modifier.append(
186
+ Filter(
187
+ query_str="filter[updated_at_gte]="
188
+ + updated_at_gte.astimezone(timezone.utc)
189
+ .replace(tzinfo=None)
190
+ .isoformat(timespec="milliseconds")
191
+ + "Z"
192
+ )
193
+ )
194
+ if updated_at_lte is not None:
195
+ modifier.append(
196
+ Filter(
197
+ query_str="filter[updated_at_lte]="
198
+ + updated_at_lte.astimezone(timezone.utc)
199
+ .replace(tzinfo=None)
200
+ .isoformat(timespec="milliseconds")
201
+ + "Z"
202
+ )
203
+ )
204
+ if updated_at_gt is not None:
205
+ modifier.append(
206
+ Filter(
207
+ query_str="filter[updated_at_gt]="
208
+ + updated_at_gt.astimezone(timezone.utc)
209
+ .replace(tzinfo=None)
210
+ .isoformat(timespec="milliseconds")
211
+ + "Z"
212
+ )
213
+ )
214
+ if updated_at_lt is not None:
215
+ modifier.append(
216
+ Filter(
217
+ query_str="filter[updated_at_lt]="
218
+ + updated_at_lt.astimezone(timezone.utc)
219
+ .replace(tzinfo=None)
220
+ .isoformat(timespec="milliseconds")
221
+ + "Z"
222
+ )
223
+ )
224
+
225
+ # Table definition
226
+ tabledef: TableDef = [
227
+ {"header": Column("Id", no_wrap=True), "column": "id"},
228
+ {"header": "Name", "column": "name"},
229
+ {"header": "Created", "column": "created_at"},
230
+ {"header": "Updated", "column": "updated_at"},
231
+ ]
232
+
233
+ async with Connection() as conn:
234
+ await list_resources(ctx, AccountBase(conn, api_schema), tabledef, modifier)
235
+
236
+
237
+ @app.async_command(help="Get account with account id")
238
+ async def show(
239
+ ctx: typer.Context,
240
+ account_id: Annotated[UUID, typer.Argument(help="Resource ID to show")],
241
+ ):
242
+ # Show resource
243
+ try:
244
+ async with Connection() as conn:
245
+ ctrl = AccountBase(conn, api_schema)
246
+ model = await ctrl.fetch(account_id)
247
+
248
+ show_resource(ctx, model)
249
+ except DocumentError as e:
250
+ await print_document_error(e)
251
+
252
+
253
+ @app.async_command(name="list-user-roles", help="List all user-roles for an account")
254
+ async def list_user_roles(
255
+ ctx: typer.Context,
256
+ account_id: Annotated[UUID, typer.Argument(help="Parent resource ID")],
257
+ account: Annotated[Optional[UUID], typer.Option(help="The account")] = None,
258
+ user: Annotated[Optional[UUID], typer.Option(help="The user")] = None,
259
+ role: Annotated[Optional[UUID], typer.Option(help="The role")] = None,
260
+ created_at: Annotated[
261
+ Optional[datetime], typer.Option(help="Timestamp when created (exact match)")
262
+ ] = None,
263
+ created_at_gte: Annotated[
264
+ Optional[datetime],
265
+ typer.Option(help="Timestamp when created (greater than or equal)"),
266
+ ] = None,
267
+ created_at_lte: Annotated[
268
+ Optional[datetime],
269
+ typer.Option(help="Timestamp when created (less than or equal)"),
270
+ ] = None,
271
+ created_at_gt: Annotated[
272
+ Optional[datetime], typer.Option(help="Timestamp when created (greater than)")
273
+ ] = None,
274
+ created_at_lt: Annotated[
275
+ Optional[datetime], typer.Option(help="Timestamp when created (less than)")
276
+ ] = None,
277
+ updated_at: Annotated[
278
+ Optional[datetime],
279
+ typer.Option(help="Timestamp when last updated (exact match)"),
280
+ ] = None,
281
+ updated_at_gte: Annotated[
282
+ Optional[datetime],
283
+ typer.Option(help="Timestamp when last updated (greater than or equal)"),
284
+ ] = None,
285
+ updated_at_lte: Annotated[
286
+ Optional[datetime],
287
+ typer.Option(help="Timestamp when last updated (less than or equal)"),
288
+ ] = None,
289
+ updated_at_gt: Annotated[
290
+ Optional[datetime],
291
+ typer.Option(help="Timestamp when last updated (greater than)"),
292
+ ] = None,
293
+ updated_at_lt: Annotated[
294
+ Optional[datetime], typer.Option(help="Timestamp when last updated (less than)")
295
+ ] = None,
296
+ ):
297
+ """List all user-roles for an account"""
298
+ try:
299
+ async with Connection() as conn:
300
+ # Fetch parent resource
301
+ parent_ctrl = AccountBase(conn, api_schema)
302
+ parent_model = await parent_ctrl.fetch(account_id)
303
+
304
+ # Build modifier for filtering and includes
305
+ modifier = []
306
+
307
+ if account is not None:
308
+ modifier.append(Filter(account=str(account)))
309
+
310
+ if user is not None:
311
+ modifier.append(Filter(user=str(user)))
312
+
313
+ if role is not None:
314
+ modifier.append(Filter(role=str(role)))
315
+
316
+ if created_at is not None:
317
+ modifier.append(
318
+ Filter(
319
+ query_str="filter[created_at]="
320
+ + created_at.astimezone(timezone.utc)
321
+ .replace(tzinfo=None)
322
+ .isoformat(timespec="milliseconds")
323
+ + "Z"
324
+ )
325
+ )
326
+ if created_at_gte is not None:
327
+ modifier.append(
328
+ Filter(
329
+ query_str="filter[created_at_gte]="
330
+ + created_at_gte.astimezone(timezone.utc)
331
+ .replace(tzinfo=None)
332
+ .isoformat(timespec="milliseconds")
333
+ + "Z"
334
+ )
335
+ )
336
+ if created_at_lte is not None:
337
+ modifier.append(
338
+ Filter(
339
+ query_str="filter[created_at_lte]="
340
+ + created_at_lte.astimezone(timezone.utc)
341
+ .replace(tzinfo=None)
342
+ .isoformat(timespec="milliseconds")
343
+ + "Z"
344
+ )
345
+ )
346
+ if created_at_gt is not None:
347
+ modifier.append(
348
+ Filter(
349
+ query_str="filter[created_at_gt]="
350
+ + created_at_gt.astimezone(timezone.utc)
351
+ .replace(tzinfo=None)
352
+ .isoformat(timespec="milliseconds")
353
+ + "Z"
354
+ )
355
+ )
356
+ if created_at_lt is not None:
357
+ modifier.append(
358
+ Filter(
359
+ query_str="filter[created_at_lt]="
360
+ + created_at_lt.astimezone(timezone.utc)
361
+ .replace(tzinfo=None)
362
+ .isoformat(timespec="milliseconds")
363
+ + "Z"
364
+ )
365
+ )
366
+
367
+ if updated_at is not None:
368
+ modifier.append(
369
+ Filter(
370
+ query_str="filter[updated_at]="
371
+ + updated_at.astimezone(timezone.utc)
372
+ .replace(tzinfo=None)
373
+ .isoformat(timespec="milliseconds")
374
+ + "Z"
375
+ )
376
+ )
377
+ if updated_at_gte is not None:
378
+ modifier.append(
379
+ Filter(
380
+ query_str="filter[updated_at_gte]="
381
+ + updated_at_gte.astimezone(timezone.utc)
382
+ .replace(tzinfo=None)
383
+ .isoformat(timespec="milliseconds")
384
+ + "Z"
385
+ )
386
+ )
387
+ if updated_at_lte is not None:
388
+ modifier.append(
389
+ Filter(
390
+ query_str="filter[updated_at_lte]="
391
+ + updated_at_lte.astimezone(timezone.utc)
392
+ .replace(tzinfo=None)
393
+ .isoformat(timespec="milliseconds")
394
+ + "Z"
395
+ )
396
+ )
397
+ if updated_at_gt is not None:
398
+ modifier.append(
399
+ Filter(
400
+ query_str="filter[updated_at_gt]="
401
+ + updated_at_gt.astimezone(timezone.utc)
402
+ .replace(tzinfo=None)
403
+ .isoformat(timespec="milliseconds")
404
+ + "Z"
405
+ )
406
+ )
407
+ if updated_at_lt is not None:
408
+ modifier.append(
409
+ Filter(
410
+ query_str="filter[updated_at_lt]="
411
+ + updated_at_lt.astimezone(timezone.utc)
412
+ .replace(tzinfo=None)
413
+ .isoformat(timespec="milliseconds")
414
+ + "Z"
415
+ )
416
+ )
417
+
418
+ # Table definition
419
+ tabledef: TableDef = [
420
+ {"header": Column("Id", no_wrap=True), "column": "id"},
421
+ {"header": "Id", "column": "id"},
422
+ {"header": "Created", "column": "created_at"},
423
+ {"header": "Updated", "column": "updated_at"},
424
+ ]
425
+
426
+ # List related resources
427
+ await list_relation_resources(
428
+ ctx, parent_model, "user-roles", tabledef, modifier
429
+ )
430
+ except DocumentError as e:
431
+ await print_document_error(e)