cacholong-cloud-cli 0.3.0__py3-none-any.whl

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 (39) hide show
  1. cacholong_cli/AsyncTyper.py +17 -0
  2. cacholong_cli/__init__.py +0 -0
  3. cacholong_cli/cli.py +110 -0
  4. cacholong_cli/commands/accounts.py +105 -0
  5. cacholong_cli/commands/addresses.py +280 -0
  6. cacholong_cli/commands/companies.py +100 -0
  7. cacholong_cli/commands/dns_records.py +275 -0
  8. cacholong_cli/commands/dns_templates.py +141 -0
  9. cacholong_cli/commands/dns_zones.py +277 -0
  10. cacholong_cli/commands/products.py +121 -0
  11. cacholong_cli/commands/purchases.py +127 -0
  12. cacholong_cli/common.py +179 -0
  13. cacholong_cli/connection.py +18 -0
  14. cacholong_cloud_cli-0.3.0.dist-info/METADATA +115 -0
  15. cacholong_cloud_cli-0.3.0.dist-info/RECORD +39 -0
  16. cacholong_cloud_cli-0.3.0.dist-info/WHEEL +4 -0
  17. cacholong_cloud_cli-0.3.0.dist-info/entry_points.txt +3 -0
  18. cacholong_sdk/__init__.py +18 -0
  19. cacholong_sdk/account.py +14 -0
  20. cacholong_sdk/address.py +14 -0
  21. cacholong_sdk/api_schema.py +124 -0
  22. cacholong_sdk/common.py +119 -0
  23. cacholong_sdk/company.py +14 -0
  24. cacholong_sdk/connection.py +22 -0
  25. cacholong_sdk/dns_record.py +14 -0
  26. cacholong_sdk/dns_template.py +14 -0
  27. cacholong_sdk/dns_zone.py +14 -0
  28. cacholong_sdk/exception.py +7 -0
  29. cacholong_sdk/product.py +14 -0
  30. cacholong_sdk/purchase.py +14 -0
  31. jsonapi_client/__init__.py +42 -0
  32. jsonapi_client/common.py +186 -0
  33. jsonapi_client/document.py +161 -0
  34. jsonapi_client/exceptions.py +62 -0
  35. jsonapi_client/filter.py +155 -0
  36. jsonapi_client/objects.py +187 -0
  37. jsonapi_client/relationships.py +447 -0
  38. jsonapi_client/resourceobject.py +656 -0
  39. jsonapi_client/session.py +755 -0
@@ -0,0 +1,275 @@
1
+ import asyncio
2
+ import typer
3
+ from typing import List, Optional
4
+ from typing_extensions import Annotated
5
+ from rich.table import Column
6
+ from uuid import UUID
7
+ from cacholong_cli.AsyncTyper import AsyncTyper
8
+ from cacholong_cli.common import (
9
+ list_resources,
10
+ list_relation_resources,
11
+ show_resource,
12
+ print_document_error,
13
+ )
14
+ from cacholong_cli.connection import Connection
15
+ from cacholong_sdk import Filter, Inclusion, DocumentError, ResourceTuple
16
+ from cacholong_sdk import DnsRecord, DnsRecordModel
17
+
18
+ # Create typer object
19
+ app = AsyncTyper()
20
+
21
+
22
+ @app.async_command()
23
+ async def list(
24
+ ctx: typer.Context,
25
+ external_service_provider_status: Annotated[
26
+ Optional[str], typer.Option(help="Status for external service provider.")
27
+ ] = None,
28
+ dns_record_type: Annotated[
29
+ Optional[str],
30
+ typer.Option(
31
+ help="Depending on DNS record type name, content, ttl and priority will be validated. Only record types mentioned are allowed and NS record type is only available for certain users."
32
+ ),
33
+ ] = None,
34
+ name: Annotated[
35
+ Optional[str],
36
+ typer.Option(
37
+ help="For most records this must be a valid domain (SRV, TLSA and NS records follow different rules). When dns template is given, placeholder $domain$ must be used. When dns zone is given, name must be identical to dns zone domain fqdn. It is not allowed to end the name with a point."
38
+ ),
39
+ ] = None,
40
+ content: Annotated[
41
+ Optional[str],
42
+ typer.Option(
43
+ help="Content differs for each DNS record type. When dns template is given, placeholder $domain$ is allowed for some records (for example CAA or CNAME records). Only TXT records can be longer then 255 chars."
44
+ ),
45
+ ] = None,
46
+ ttl: Annotated[
47
+ Optional[str],
48
+ typer.Option(
49
+ help='Time to live in seconds, limited to allowed values. Please note that a TTL of 1 (one) can have a special meaning (Cloudflare considers this value "automatic").'
50
+ ),
51
+ ] = None,
52
+ priority: Annotated[
53
+ Optional[str], typer.Option(help="Prohibited, except for MX and SRV record.")
54
+ ] = None,
55
+ created_at: Annotated[Optional[str], typer.Option(help="")] = None,
56
+ updated_at: Annotated[Optional[str], typer.Option(help="")] = None,
57
+ dns_zone: Annotated[
58
+ Optional[UUID],
59
+ typer.Option(
60
+ help="Existing dns zone. Required unless dns template is given. Only available for certain users, dnz zone should not be administratively disabled. Must be unique with type, name, content and priority."
61
+ ),
62
+ ] = None,
63
+ dns_template: Annotated[
64
+ Optional[UUID],
65
+ typer.Option(
66
+ help="Existing dns template. Required unless dns zone is given. Must be unique with type, name, content and priority."
67
+ ),
68
+ ] = None,
69
+ ):
70
+ # Build modifier
71
+ modifier = []
72
+ if external_service_provider_status is not None:
73
+ modifier.append(
74
+ Filter(
75
+ query_str="filter[external_service_provider_status]="
76
+ + str(external_service_provider_status)
77
+ )
78
+ )
79
+ if dns_record_type is not None:
80
+ modifier.append(
81
+ Filter(query_str="filter[dns_record_type]=" + str(dns_record_type))
82
+ )
83
+ if name is not None:
84
+ modifier.append(Filter(name=name))
85
+ if content is not None:
86
+ modifier.append(Filter(content=content))
87
+ if ttl is not None:
88
+ modifier.append(Filter(ttl=ttl))
89
+ if priority is not None:
90
+ modifier.append(Filter(priority=priority))
91
+ if created_at is not None:
92
+ modifier.append(Filter(query_str="filter[created_at]=" + str(created_at)))
93
+ if updated_at is not None:
94
+ modifier.append(Filter(query_str="filter[updated_at]=" + str(updated_at)))
95
+ if dns_zone is not None:
96
+ modifier.append(Filter(query_str="filter[dns-zone]=" + str(dns_zone)))
97
+ if dns_template is not None:
98
+ modifier.append(Filter(query_str="filter[dns-template]=" + str(dns_template)))
99
+
100
+ # Table definition
101
+ tabledef = [
102
+ {"header": Column("Id", no_wrap=True), "column": "id"},
103
+ {"header": "Name", "column": "name"},
104
+ {"header": "Dns record type", "column": "dns_record_type"},
105
+ {"header": "Content", "column": "content"},
106
+ {
107
+ "header": "External service provider status",
108
+ "column": "external_service_provider_status",
109
+ },
110
+ {"header": "Created", "column": "created_at"},
111
+ {"header": "Updated", "column": "updated_at"},
112
+ ]
113
+ async with Connection() as conn:
114
+ await list_resources(ctx, DnsRecord(conn), tabledef, modifier)
115
+
116
+
117
+ @app.async_command()
118
+ async def show(
119
+ ctx: typer.Context,
120
+ dns_record_id: Annotated[UUID, typer.Argument()],
121
+ ):
122
+ # Show resource
123
+ try:
124
+ async with Connection() as conn:
125
+ ctrl = DnsRecord(conn)
126
+ model = await ctrl.fetch(dns_record_id)
127
+
128
+ show_resource(ctx, model)
129
+ except DocumentError as e:
130
+ await print_document_error(e)
131
+
132
+
133
+ @app.async_command()
134
+ async def create(
135
+ ctx: typer.Context,
136
+ dns_record_type: Annotated[
137
+ str,
138
+ typer.Option(
139
+ help="Depending on DNS record type name, content, ttl and priority will be validated. Only record types mentioned are allowed and NS record type is only available for certain users."
140
+ ),
141
+ ],
142
+ name: Annotated[
143
+ str,
144
+ typer.Option(
145
+ help="For most records this must be a valid domain (SRV, TLSA and NS records follow different rules). When dns template is given, placeholder $domain$ must be used. When dns zone is given, name must be identical to dns zone domain fqdn. It is not allowed to end the name with a point."
146
+ ),
147
+ ],
148
+ content: Annotated[
149
+ str,
150
+ typer.Option(
151
+ help="Content differs for each DNS record type. When dns template is given, placeholder $domain$ is allowed for some records (for example CAA or CNAME records). Only TXT records can be longer then 255 chars."
152
+ ),
153
+ ],
154
+ ttl: Annotated[
155
+ Optional[int],
156
+ typer.Option(
157
+ help='Time to live in seconds, limited to allowed values. Please note that a TTL of 1 (one) can have a special meaning (Cloudflare considers this value "automatic").'
158
+ ),
159
+ ] = None,
160
+ priority: Annotated[
161
+ Optional[int], typer.Option(help="Prohibited, except for MX and SRV record.")
162
+ ] = None,
163
+ dns_zone: Annotated[
164
+ Optional[UUID],
165
+ typer.Option(
166
+ help="Existing dns zone. Required unless dns template is given. Only available for certain users, dnz zone should not be administratively disabled. Must be unique with type, name, content and priority."
167
+ ),
168
+ ] = None,
169
+ dns_template: Annotated[
170
+ Optional[UUID],
171
+ typer.Option(
172
+ help="Existing dns template. Required unless dns zone is given. Must be unique with type, name, content and priority."
173
+ ),
174
+ ] = None,
175
+ ):
176
+ try:
177
+ async with Connection() as conn:
178
+ ctrl = DnsRecord(conn)
179
+ model = ctrl.create()
180
+ model["dns_record_type"] = dns_record_type
181
+ model["name"] = name
182
+ model["content"] = content
183
+ if ttl is not None:
184
+ model["ttl"] = ttl
185
+ if priority is not None:
186
+ model["priority"] = priority
187
+ if dns_zone is not None:
188
+ model["dns-zone"] = ResourceTuple(dns_zone, "dns-zones")
189
+ if dns_template is not None:
190
+ model["dns-template"] = ResourceTuple(dns_template, "dns-templates")
191
+ await ctrl.store(model, ctx.obj["create_issue"])
192
+
193
+ show_resource(ctx, model)
194
+ except DocumentError as e:
195
+ await print_document_error(e)
196
+
197
+
198
+ @app.async_command()
199
+ async def update(
200
+ ctx: typer.Context,
201
+ dns_record_id: Annotated[UUID, typer.Argument()],
202
+ dns_record_type: Annotated[
203
+ Optional[str],
204
+ typer.Option(
205
+ help="Depending on DNS record type name, content, ttl and priority will be validated. Only record types mentioned are allowed and NS record type is only available for certain users."
206
+ ),
207
+ ] = None,
208
+ name: Annotated[
209
+ Optional[str],
210
+ typer.Option(
211
+ help="For most records this must be a valid domain (SRV, TLSA and NS records follow different rules). When dns template is given, placeholder $domain$ must be used. When dns zone is given, name must be identical to dns zone domain fqdn. It is not allowed to end the name with a point."
212
+ ),
213
+ ] = None,
214
+ content: Annotated[
215
+ Optional[str],
216
+ typer.Option(
217
+ help="Content differs for each DNS record type. When dns template is given, placeholder $domain$ is allowed for some records (for example CAA or CNAME records). Only TXT records can be longer then 255 chars."
218
+ ),
219
+ ] = None,
220
+ ttl: Annotated[
221
+ Optional[int],
222
+ typer.Option(
223
+ help='Time to live in seconds, limited to allowed values. Please note that a TTL of 1 (one) can have a special meaning (Cloudflare considers this value "automatic").'
224
+ ),
225
+ ] = None,
226
+ priority: Annotated[
227
+ Optional[int], typer.Option(help="Prohibited, except for MX and SRV record.")
228
+ ] = None,
229
+ dns_zone: Annotated[
230
+ Optional[UUID],
231
+ typer.Option(
232
+ help="Existing dns zone. Required unless dns template is given. Only available for certain users, dnz zone should not be administratively disabled. Must be unique with type, name, content and priority."
233
+ ),
234
+ ] = None,
235
+ dns_template: Annotated[
236
+ Optional[UUID],
237
+ typer.Option(
238
+ help="Existing dns template. Required unless dns zone is given. Must be unique with type, name, content and priority."
239
+ ),
240
+ ] = None,
241
+ ):
242
+ try:
243
+ async with Connection() as conn:
244
+ ctrl = DnsRecord(conn)
245
+ model = await ctrl.fetch(dns_record_id)
246
+ if dns_record_type is not None:
247
+ model["dns_record_type"] = dns_record_type
248
+ if name is not None:
249
+ model["name"] = name
250
+ if content is not None:
251
+ model["content"] = content
252
+ if ttl is not None:
253
+ model["ttl"] = ttl
254
+ if priority is not None:
255
+ model["priority"] = priority
256
+ if dns_zone is not None:
257
+ model["dns-zone"].set(dns_zone, "dns-zones")
258
+ if dns_template is not None:
259
+ model["dns-template"].set(dns_template, "dns-templates")
260
+ except DocumentError as e:
261
+ await print_document_error(e)
262
+
263
+
264
+ @app.async_command()
265
+ async def delete(
266
+ ctx: typer.Context,
267
+ dns_record_id: Annotated[List[UUID], typer.Argument()],
268
+ ):
269
+ try:
270
+ async with Connection() as conn, asyncio.TaskGroup() as tg:
271
+ ctrl = DnsRecord(conn)
272
+ for resource_id in dns_record_id:
273
+ tg.create_task(ctrl.destroy(resource_id))
274
+ except DocumentError as e:
275
+ await print_document_error(e)
@@ -0,0 +1,141 @@
1
+ import asyncio
2
+ import typer
3
+ from typing import List, Optional
4
+ from typing_extensions import Annotated
5
+ from rich.table import Column
6
+ from uuid import UUID
7
+ from cacholong_cli.AsyncTyper import AsyncTyper
8
+ from cacholong_cli.common import (
9
+ list_resources,
10
+ list_relation_resources,
11
+ show_resource,
12
+ print_document_error,
13
+ )
14
+ from cacholong_cli.connection import Connection
15
+ from cacholong_sdk import Filter, Inclusion, DocumentError, ResourceTuple
16
+ from cacholong_sdk import DnsTemplate, DnsTemplateModel
17
+
18
+ # Create typer object
19
+ app = AsyncTyper()
20
+
21
+
22
+ @app.async_command()
23
+ async def list(
24
+ ctx: typer.Context,
25
+ name: Annotated[
26
+ Optional[str], typer.Option(help="Must be unique or unique with given account.")
27
+ ] = None,
28
+ created_at: Annotated[Optional[str], typer.Option(help="")] = None,
29
+ updated_at: Annotated[Optional[str], typer.Option(help="")] = None,
30
+ account: Annotated[
31
+ Optional[UUID],
32
+ typer.Option(
33
+ help="Existing account. Some users can set this to null, meaning template is not limited to an account."
34
+ ),
35
+ ] = None,
36
+ ):
37
+ # Build modifier
38
+ modifier = []
39
+ if name is not None:
40
+ modifier.append(Filter(name=name))
41
+ if created_at is not None:
42
+ modifier.append(Filter(query_str="filter[created_at]=" + str(created_at)))
43
+ if updated_at is not None:
44
+ modifier.append(Filter(query_str="filter[updated_at]=" + str(updated_at)))
45
+ if account is not None:
46
+ modifier.append(Filter(account=str(account)))
47
+ modifier.append(Inclusion("account"))
48
+
49
+ # Table definition
50
+ tabledef = [
51
+ {"header": Column("Id", no_wrap=True), "column": "id"},
52
+ {"header": "Account", "column": "account", "nested_column": "name"},
53
+ {"header": "Name", "column": "name"},
54
+ {"header": "Created", "column": "created_at"},
55
+ {"header": "Updated", "column": "updated_at"},
56
+ ]
57
+ async with Connection() as conn:
58
+ await list_resources(ctx, DnsTemplate(conn), tabledef, modifier)
59
+
60
+
61
+ @app.async_command()
62
+ async def show(
63
+ ctx: typer.Context,
64
+ dns_template_id: Annotated[UUID, typer.Argument()],
65
+ ):
66
+ # Show resource
67
+ try:
68
+ async with Connection() as conn:
69
+ ctrl = DnsTemplate(conn)
70
+ model = await ctrl.fetch(dns_template_id)
71
+
72
+ show_resource(ctx, model)
73
+ except DocumentError as e:
74
+ await print_document_error(e)
75
+
76
+
77
+ @app.async_command()
78
+ async def create(
79
+ ctx: typer.Context,
80
+ name: Annotated[
81
+ str, typer.Option(help="Must be unique or unique with given account.")
82
+ ],
83
+ account: Annotated[
84
+ Optional[UUID],
85
+ typer.Option(
86
+ help="Existing account. Some users can set this to null, meaning template is not limited to an account."
87
+ ),
88
+ ] = None,
89
+ ):
90
+ try:
91
+ async with Connection() as conn:
92
+ ctrl = DnsTemplate(conn)
93
+ model = ctrl.create()
94
+ model["name"] = name
95
+ if account is not None:
96
+ model["account"] = ResourceTuple(account, "accounts")
97
+ await ctrl.store(model, ctx.obj["create_issue"])
98
+
99
+ show_resource(ctx, model)
100
+ except DocumentError as e:
101
+ await print_document_error(e)
102
+
103
+
104
+ @app.async_command()
105
+ async def update(
106
+ ctx: typer.Context,
107
+ dns_template_id: Annotated[UUID, typer.Argument()],
108
+ name: Annotated[
109
+ Optional[str], typer.Option(help="Must be unique or unique with given account.")
110
+ ] = None,
111
+ account: Annotated[
112
+ Optional[UUID],
113
+ typer.Option(
114
+ help="Existing account. Some users can set this to null, meaning template is not limited to an account."
115
+ ),
116
+ ] = None,
117
+ ):
118
+ try:
119
+ async with Connection() as conn:
120
+ ctrl = DnsTemplate(conn)
121
+ model = await ctrl.fetch(dns_template_id)
122
+ if name is not None:
123
+ model["name"] = name
124
+ if account is not None:
125
+ model["account"].set(account, "accounts")
126
+ except DocumentError as e:
127
+ await print_document_error(e)
128
+
129
+
130
+ @app.async_command()
131
+ async def delete(
132
+ ctx: typer.Context,
133
+ dns_template_id: Annotated[List[UUID], typer.Argument()],
134
+ ):
135
+ try:
136
+ async with Connection() as conn, asyncio.TaskGroup() as tg:
137
+ ctrl = DnsTemplate(conn)
138
+ for resource_id in dns_template_id:
139
+ tg.create_task(ctrl.destroy(resource_id))
140
+ except DocumentError as e:
141
+ await print_document_error(e)
@@ -0,0 +1,277 @@
1
+ import asyncio
2
+ import typer
3
+ from typing import List, Optional
4
+ from typing_extensions import Annotated
5
+ from rich.table import Column
6
+ from uuid import UUID
7
+ from cacholong_cli.AsyncTyper import AsyncTyper
8
+ from cacholong_cli.common import (
9
+ list_resources,
10
+ list_relation_resources,
11
+ show_resource,
12
+ print_document_error,
13
+ )
14
+ from cacholong_cli.connection import Connection
15
+ from cacholong_sdk import Filter, Inclusion, DocumentError, ResourceTuple
16
+ from cacholong_sdk import DnsZone, DnsZoneModel
17
+
18
+ # Create typer object
19
+ app = AsyncTyper()
20
+
21
+
22
+ @app.async_command()
23
+ async def list(
24
+ ctx: typer.Context,
25
+ external_service_provider_status: Annotated[
26
+ Optional[str], typer.Option(help="Status for external service provider.")
27
+ ] = None,
28
+ domain: Annotated[
29
+ Optional[str],
30
+ typer.Option(
31
+ help="Valid when provided with a domain and TLD (without a protocol)."
32
+ ),
33
+ ] = None,
34
+ active: Annotated[
35
+ Optional[str], typer.Option(help="Is dns zone active or not?")
36
+ ] = None,
37
+ administratively_disabled: Annotated[
38
+ Optional[str],
39
+ typer.Option(
40
+ help="Is dns zone administratively disabled or not? Only visible for certain users."
41
+ ),
42
+ ] = None,
43
+ dnssec: Annotated[
44
+ Optional[str], typer.Option(help="Is dnssec enabled or not?")
45
+ ] = None,
46
+ dnssec_status: Annotated[
47
+ Optional[str], typer.Option(help="Status of DNSSEC.")
48
+ ] = None,
49
+ dnssec_flags: Annotated[
50
+ Optional[str], typer.Option(help="Flag for DNSSEC record.")
51
+ ] = None,
52
+ dnssec_algorithm: Annotated[
53
+ Optional[str], typer.Option(help="Algorithm key code.")
54
+ ] = None,
55
+ dnssec_public_key: Annotated[
56
+ Optional[str], typer.Option(help="Public key for DS record.")
57
+ ] = None,
58
+ created_at: Annotated[Optional[str], typer.Option(help="")] = None,
59
+ updated_at: Annotated[Optional[str], typer.Option(help="")] = None,
60
+ account: Annotated[
61
+ Optional[UUID], typer.Option(help="Account for this dns zone.")
62
+ ] = None,
63
+ name_server_group: Annotated[
64
+ Optional[UUID],
65
+ typer.Option(help="Name server groups for this dns zone. Readonly."),
66
+ ] = None,
67
+ purchase: Annotated[
68
+ Optional[UUID],
69
+ typer.Option(
70
+ help="Purchase for this dns zone. Required if no product is provided."
71
+ ),
72
+ ] = None,
73
+ product: Annotated[
74
+ Optional[UUID],
75
+ typer.Option(
76
+ help="Product for this dns zone. Required if no purchase is provided."
77
+ ),
78
+ ] = None,
79
+ ):
80
+ # Build modifier
81
+ modifier = []
82
+ if external_service_provider_status is not None:
83
+ modifier.append(
84
+ Filter(
85
+ query_str="filter[external_service_provider_status]="
86
+ + str(external_service_provider_status)
87
+ )
88
+ )
89
+ if domain is not None:
90
+ modifier.append(Filter(domain=domain))
91
+ if active is not None:
92
+ modifier.append(Filter(active=active))
93
+ if administratively_disabled is not None:
94
+ modifier.append(
95
+ Filter(
96
+ query_str="filter[administratively_disabled]="
97
+ + str(administratively_disabled)
98
+ )
99
+ )
100
+ if dnssec is not None:
101
+ modifier.append(Filter(dnssec=dnssec))
102
+ if dnssec_status is not None:
103
+ modifier.append(Filter(query_str="filter[dnssec_status]=" + str(dnssec_status)))
104
+ if dnssec_flags is not None:
105
+ modifier.append(Filter(query_str="filter[dnssec_flags]=" + str(dnssec_flags)))
106
+ if dnssec_algorithm is not None:
107
+ modifier.append(
108
+ Filter(query_str="filter[dnssec_algorithm]=" + str(dnssec_algorithm))
109
+ )
110
+ if dnssec_public_key is not None:
111
+ modifier.append(
112
+ Filter(query_str="filter[dnssec_public_key]=" + str(dnssec_public_key))
113
+ )
114
+ if created_at is not None:
115
+ modifier.append(Filter(query_str="filter[created_at]=" + str(created_at)))
116
+ if updated_at is not None:
117
+ modifier.append(Filter(query_str="filter[updated_at]=" + str(updated_at)))
118
+ if account is not None:
119
+ modifier.append(Filter(account=str(account)))
120
+ if name_server_group is not None:
121
+ modifier.append(
122
+ Filter(query_str="filter[name-server-group]=" + str(name_server_group))
123
+ )
124
+ if purchase is not None:
125
+ modifier.append(Filter(purchase=str(purchase)))
126
+ if product is not None:
127
+ modifier.append(Filter(product=str(product)))
128
+ modifier.append(Inclusion("account"))
129
+
130
+ # Table definition
131
+ tabledef = [
132
+ {"header": Column("Id", no_wrap=True), "column": "id"},
133
+ {"header": "Account", "column": "account", "nested_column": "name"},
134
+ {"header": "Domain", "column": "domain"},
135
+ {"header": "Active", "column": "active"},
136
+ {"header": "Dnssec", "column": "dnssec"},
137
+ {
138
+ "header": "External service provider status",
139
+ "column": "external_service_provider_status",
140
+ },
141
+ {"header": "Created", "column": "created_at"},
142
+ {"header": "Updated", "column": "updated_at"},
143
+ ]
144
+ async with Connection() as conn:
145
+ await list_resources(ctx, DnsZone(conn), tabledef, modifier)
146
+
147
+
148
+ @app.async_command()
149
+ async def show(
150
+ ctx: typer.Context,
151
+ dns_zone_id: Annotated[UUID, typer.Argument()],
152
+ ):
153
+ # Show resource
154
+ try:
155
+ async with Connection() as conn:
156
+ ctrl = DnsZone(conn)
157
+ model = await ctrl.fetch(dns_zone_id)
158
+
159
+ show_resource(ctx, model)
160
+ except DocumentError as e:
161
+ await print_document_error(e)
162
+
163
+
164
+ @app.async_command()
165
+ async def create(
166
+ ctx: typer.Context,
167
+ domain: Annotated[
168
+ str,
169
+ typer.Option(
170
+ help="Valid when provided with a domain and TLD (without a protocol)."
171
+ ),
172
+ ],
173
+ account: Annotated[UUID, typer.Option(help="Account for this dns zone.")],
174
+ active: Annotated[
175
+ Optional[bool], typer.Option(help="Is dns zone active or not?")
176
+ ] = None,
177
+ dnssec: Annotated[
178
+ Optional[bool], typer.Option(help="Is dnssec enabled or not?")
179
+ ] = None,
180
+ purchase: Annotated[
181
+ Optional[UUID],
182
+ typer.Option(
183
+ help="Purchase for this dns zone. Required if no product is provided."
184
+ ),
185
+ ] = None,
186
+ product: Annotated[
187
+ Optional[UUID],
188
+ typer.Option(
189
+ help="Product for this dns zone. Required if no purchase is provided."
190
+ ),
191
+ ] = None,
192
+ ):
193
+ try:
194
+ async with Connection() as conn:
195
+ ctrl = DnsZone(conn)
196
+ model = ctrl.create()
197
+ model["domain"] = domain
198
+ if active is not None:
199
+ model["active"] = active
200
+ if dnssec is not None:
201
+ model["dnssec"] = dnssec
202
+ model["account"] = ResourceTuple(account, "accounts")
203
+ if purchase is not None:
204
+ model["purchase"] = ResourceTuple(purchase, "purchases")
205
+ if product is not None:
206
+ model["product"] = ResourceTuple(product, "products")
207
+ await ctrl.store(model, ctx.obj["create_issue"])
208
+
209
+ show_resource(ctx, model)
210
+ except DocumentError as e:
211
+ await print_document_error(e)
212
+
213
+
214
+ @app.async_command()
215
+ async def update(
216
+ ctx: typer.Context,
217
+ dns_zone_id: Annotated[UUID, typer.Argument()],
218
+ domain: Annotated[
219
+ Optional[str],
220
+ typer.Option(
221
+ help="Valid when provided with a domain and TLD (without a protocol)."
222
+ ),
223
+ ] = None,
224
+ active: Annotated[
225
+ Optional[bool], typer.Option(help="Is dns zone active or not?")
226
+ ] = None,
227
+ dnssec: Annotated[
228
+ Optional[bool], typer.Option(help="Is dnssec enabled or not?")
229
+ ] = None,
230
+ account: Annotated[
231
+ Optional[UUID], typer.Option(help="Account for this dns zone.")
232
+ ] = None,
233
+ purchase: Annotated[
234
+ Optional[UUID],
235
+ typer.Option(
236
+ help="Purchase for this dns zone. Required if no product is provided."
237
+ ),
238
+ ] = None,
239
+ product: Annotated[
240
+ Optional[UUID],
241
+ typer.Option(
242
+ help="Product for this dns zone. Required if no purchase is provided."
243
+ ),
244
+ ] = None,
245
+ ):
246
+ try:
247
+ async with Connection() as conn:
248
+ ctrl = DnsZone(conn)
249
+ model = await ctrl.fetch(dns_zone_id)
250
+ if domain is not None:
251
+ model["domain"] = domain
252
+ if active is not None:
253
+ model["active"] = active
254
+ if dnssec is not None:
255
+ model["dnssec"] = dnssec
256
+ if account is not None:
257
+ model["account"].set(account, "accounts")
258
+ if purchase is not None:
259
+ model["purchase"].set(purchase, "purchases")
260
+ if product is not None:
261
+ model["product"].set(product, "products")
262
+ except DocumentError as e:
263
+ await print_document_error(e)
264
+
265
+
266
+ @app.async_command()
267
+ async def delete(
268
+ ctx: typer.Context,
269
+ dns_zone_id: Annotated[List[UUID], typer.Argument()],
270
+ ):
271
+ try:
272
+ async with Connection() as conn, asyncio.TaskGroup() as tg:
273
+ ctrl = DnsZone(conn)
274
+ for resource_id in dns_zone_id:
275
+ tg.create_task(ctrl.destroy(resource_id))
276
+ except DocumentError as e:
277
+ await print_document_error(e)