knotctl 0.0.7__py3-none-any.whl → 0.0.8__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.
knotctl/__init__.py CHANGED
@@ -7,7 +7,7 @@ import os
7
7
  import sys
8
8
  import urllib.parse
9
9
  from os import environ, mkdir
10
- from os.path import isdir, isfile, join
10
+ from os.path import isdir, isfile, islink, join, split
11
11
  from typing import Union
12
12
  from urllib.parse import urlparse
13
13
 
@@ -16,6 +16,7 @@ import requests
16
16
  import yaml
17
17
  from requests.models import HTTPBasicAuth
18
18
  from simplejson.errors import JSONDecodeError as SimplejsonJSONDecodeError
19
+
19
20
  try:
20
21
  from requests.exceptions import JSONDecodeError as RequestsJSONDecodeError
21
22
  except ImportError:
@@ -45,8 +46,7 @@ def nested_out(input, tabs="") -> str:
45
46
  string += "{}\n".format(input)
46
47
  elif isinstance(input, dict):
47
48
  for key, value in input.items():
48
- string += "{}{}: {}".format(tabs, key,
49
- nested_out(value, tabs + " "))
49
+ string += "{}{}: {}".format(tabs, key, nested_out(value, tabs + " "))
50
50
  elif isinstance(input, list):
51
51
  for entry in input:
52
52
  string += "{}\n{}".format(tabs, nested_out(entry, tabs + " "))
@@ -70,15 +70,60 @@ def run_add(url: str, jsonout: bool, headers: dict):
70
70
  out = response.json()
71
71
  if isinstance(out, list):
72
72
  for record in out:
73
- if (record["data"] == parsed["data"]
74
- and record["name"] == parsed["name"]
75
- and record["rtype"] == parsed["rtype"]):
73
+ if (
74
+ record["data"] == parsed["data"]
75
+ and record["name"] == parsed["name"]
76
+ and record["rtype"] == parsed["rtype"]
77
+ ):
76
78
  output(record, jsonout)
77
79
  break
78
80
  else:
79
81
  output(out, jsonout)
80
82
 
81
83
 
84
+ def run_log(url: str, jsonout: bool, headers: dict):
85
+ response = requests.get(url, headers=headers)
86
+ string = response.content.decode("utf-8")
87
+ if jsonout:
88
+ out = []
89
+ lines = string.splitlines()
90
+ index = 0
91
+ text = ""
92
+ timestamp = ""
93
+ while index < len(lines):
94
+ line = lines[index]
95
+ index += 1
96
+ cur_has_timestamp = line.startswith("[")
97
+ next_has_timestamp = index < len(lines) and lines[index].startswith(
98
+ "["
99
+ )
100
+ # Simple case, just one line with timestamp
101
+ if cur_has_timestamp and next_has_timestamp:
102
+ timestamp = line.split(']')[0].split('[')[1]
103
+ text = line.split(']')[1].lstrip(':').strip()
104
+ out.append({'timestamp': timestamp, 'text': text})
105
+ text = ""
106
+ timestamp = ""
107
+ # Start of multiline
108
+ elif cur_has_timestamp:
109
+ timestamp = line.split(']')[0].split('[')[1]
110
+ text = line.split(']')[1].lstrip(':').strip()
111
+ # End of multiline
112
+ elif next_has_timestamp:
113
+ text += f'\n{line.strip()}'
114
+ out.append({'timestamp': timestamp, 'text': text})
115
+ text = ""
116
+ timestamp = ""
117
+ # Middle of multiline
118
+ else:
119
+ text += f'\n{line.strip()}'
120
+
121
+ else:
122
+ out = string
123
+
124
+ output(out, jsonout)
125
+
126
+
82
127
  def run_complete(shell: Union[None, str]):
83
128
  if not shell or shell in ["bash", "zsh"]:
84
129
  os.system("register-python-argcomplete knotctl")
@@ -94,11 +139,19 @@ def run_config(
94
139
  baseurl: Union[None, str] = None,
95
140
  username: Union[None, str] = None,
96
141
  password: Union[None, str] = None,
142
+ current: Union[None, str] = None,
97
143
  ):
144
+ if current:
145
+ if os.path.islink(config_filename):
146
+ actual_path = os.readlink(config_filename)
147
+ print(actual_path.split('-')[-1])
148
+ else:
149
+ print("none")
150
+ return
98
151
  config = {"baseurl": baseurl, "username": username, "password": password}
99
152
  needed = []
100
153
  if context:
101
- symlink = f'{config_filename}-{context}'
154
+ symlink = f"{config_filename}-{context}"
102
155
  found = os.path.isfile(symlink)
103
156
  if os.path.islink(config_filename):
104
157
  os.remove(config_filename)
@@ -118,7 +171,8 @@ def run_config(
118
171
  error(
119
172
  "Can not configure without {}".format(need),
120
173
  "No {}".format(need),
121
- ))
174
+ )
175
+ )
122
176
  sys.exit(1)
123
177
  config[need] = input("Enter {}: ".format(need))
124
178
 
@@ -142,10 +196,7 @@ def run_delete(url: str, jsonout: bool, headers: dict):
142
196
  output(reply, jsonout)
143
197
 
144
198
 
145
- def run_list(url: str,
146
- jsonout: bool,
147
- headers: dict,
148
- ret=False) -> Union[None, str]:
199
+ def run_list(url: str, jsonout: bool, headers: dict, ret=False) -> Union[None, str]:
149
200
  response = requests.get(url, headers=headers)
150
201
  string = response.json()
151
202
  if ret:
@@ -176,7 +227,7 @@ def setup_url(
176
227
  url += "/{}".format(zone)
177
228
  if name and zone:
178
229
  if name.endswith(zone.rstrip(".")):
179
- name += '.'
230
+ name += "."
180
231
  url += "/records/{}".format(name)
181
232
  if zone and name and rtype:
182
233
  url += "/{}".format(rtype)
@@ -197,14 +248,16 @@ def setup_url(
197
248
  error(
198
249
  "ttl only makes sense with rtype, name and zone",
199
250
  "Missing parameter",
200
- ))
251
+ )
252
+ )
201
253
  sys.exit(1)
202
254
  if rtype and (not name or not zone):
203
255
  output(
204
256
  error(
205
257
  "rtype only makes sense with name and zone",
206
258
  "Missing parameter",
207
- ))
259
+ )
260
+ )
208
261
  sys.exit(1)
209
262
  if name and not zone:
210
263
  output(error("name only makes sense with a zone", "Missing parameter"))
@@ -246,44 +299,130 @@ def split_url(url: str) -> dict:
246
299
 
247
300
  # Entry point to program
248
301
  def main() -> int:
302
+ description = """Manage DNS records with knot dns rest api:
303
+ * https://gitlab.nic.cz/knot/knot-dns-rest"""
304
+
305
+ epilog = """
306
+ The Domain Name System specifies a database of information
307
+ elements for network resources. The types of information
308
+ elements are categorized and organized with a list of DNS
309
+ record types, the resource records (RRs). Each record has a
310
+ name, a type, an expiration time (time to live), and
311
+ type-specific data.
312
+
313
+ The following is a list of terms used in this program:
314
+ ----------------------------------------------------------------
315
+ | Vocabulary | Description |
316
+ ----------------------------------------------------------------
317
+ | zone | A DNS zone is a specific portion of the DNS |
318
+ | | namespace in the Domain Name System (DNS), |
319
+ | | which a specific organization or administrator |
320
+ | | manages. |
321
+ ----------------------------------------------------------------
322
+ | name | In the Internet, a domain name is a string that |
323
+ | | identifies a realm of administrative autonomy, |
324
+ | | authority or control. Domain names are often |
325
+ | | used to identify services provided through the |
326
+ | | Internet, such as websites, email services and |
327
+ | | more. |
328
+ ----------------------------------------------------------------
329
+ | rtype | A record type indicates the format of the data |
330
+ | | and it gives a hint of its intended use. For |
331
+ | | example, the A record is used to translate from |
332
+ | | a domain name to an IPv4 address, the NS record |
333
+ | | lists which name servers can answer lookups on |
334
+ | | a DNS zone, and the MX record specifies the |
335
+ | | mail server used to handle mail for a domain |
336
+ | | specified in an e-mail address. |
337
+ ----------------------------------------------------------------
338
+ | data | A records data is of type-specific relevance, |
339
+ | | such as the IP address for address records, or |
340
+ | | the priority and hostname for MX records. |
341
+ ----------------------------------------------------------------
342
+
343
+ This information was compiled from Wikipedia:
344
+ * https://en.wikipedia.org/wiki/DNS_zone
345
+ * https://en.wikipedia.org/wiki/Domain_Name_System
346
+ * https://en.wikipedia.org/wiki/Zone_file
347
+ """
249
348
  # Grab user input
250
- parser = argparse.ArgumentParser()
349
+ parser = argparse.ArgumentParser(
350
+ description=description,
351
+ epilog=epilog,
352
+ formatter_class=argparse.RawDescriptionHelpFormatter,
353
+ )
251
354
  parser.add_argument("--json", action=argparse.BooleanOptionalAction)
252
355
  subparsers = parser.add_subparsers(dest="command")
253
- addcmd = subparsers.add_parser("add")
356
+
357
+ add_description = "Add a new record to the zone."
358
+ addcmd = subparsers.add_parser("add", description=add_description)
254
359
  addcmd.add_argument("-d", "--data", required=True)
255
360
  addcmd.add_argument("-n", "--name", required=True)
256
361
  addcmd.add_argument("-r", "--rtype", required=True)
257
362
  addcmd.add_argument("-t", "--ttl")
258
363
  addcmd.add_argument("-z", "--zone", required=True)
259
364
 
260
- completecmd = subparsers.add_parser("completion")
365
+ auditlog_description = "Audit the log file for errors."
366
+ subparsers.add_parser("auditlog", description=auditlog_description)
367
+
368
+ changelog_description = "View the changelog of a zone."
369
+ changelogcmd = subparsers.add_parser("changelog", description=changelog_description)
370
+ changelogcmd.add_argument("-z", "--zone", required=True)
371
+
372
+ complete_description = "Generate shell completion script."
373
+ completecmd = subparsers.add_parser("completion", description=complete_description)
261
374
  completecmd.add_argument("-s", "--shell")
262
375
 
263
- configcmd = subparsers.add_parser("config")
376
+ config_description = "Configure access to knot-dns-rest-api."
377
+ configcmd = subparsers.add_parser("config", description=config_description)
264
378
  configcmd.add_argument("-b", "--baseurl")
265
379
  configcmd.add_argument("-c", "--context")
380
+ configcmd.add_argument("-C", "--current", action=argparse.BooleanOptionalAction)
266
381
  configcmd.add_argument("-p", "--password")
267
382
  configcmd.add_argument("-u", "--username")
268
383
 
269
- deletecmd = subparsers.add_parser("delete")
384
+ delete_description = "Delete a record from the zone."
385
+ deletecmd = subparsers.add_parser("delete", description=delete_description)
270
386
  deletecmd.add_argument("-d", "--data")
271
387
  deletecmd.add_argument("-n", "--name")
272
388
  deletecmd.add_argument("-r", "--rtype")
273
389
  deletecmd.add_argument("-z", "--zone", required=True)
274
390
 
275
- listcmd = subparsers.add_parser("list")
391
+ list_description = "List records in the zone."
392
+ listcmd = subparsers.add_parser("list", description=list_description)
276
393
  listcmd.add_argument("-d", "--data")
277
394
  listcmd.add_argument("-n", "--name")
278
395
  listcmd.add_argument("-r", "--rtype")
279
396
  listcmd.add_argument("-z", "--zone", required=True)
280
397
 
281
- updatecmd = subparsers.add_parser("update")
398
+ update_description = (
399
+ "Update a record in the zone. The record must exist in the zone.\n"
400
+ )
401
+ update_description += (
402
+ "In this case --data, --name, --rtype and --ttl switches are used\n"
403
+ )
404
+ update_description += (
405
+ "for searching for the appropriate record, while the --argument\n"
406
+ )
407
+ update_description += "switches are used for updating the record."
408
+ update_epilog = """Available arguments are:
409
+ data: New record data.
410
+ name: New record domain name.
411
+ rtype: New record type.
412
+ ttl: New record time to live (TTL)."""
413
+ updatecmd = subparsers.add_parser(
414
+ "update",
415
+ description=update_description,
416
+ epilog=update_epilog,
417
+ formatter_class=argparse.RawDescriptionHelpFormatter,
418
+ )
282
419
  updatecmd.add_argument(
283
420
  "-a",
284
421
  "--argument",
285
422
  nargs="*",
286
- help="Specify key - value pairs to be updated: name=dns1.example.com.",
423
+ action="append",
424
+ metavar="KEY=VALUE",
425
+ help="Specify key - value pairs to be updated: name=dns1.example.com. or data=127.0.0.1 for example. --argument can be repeated",
287
426
  required=True,
288
427
  )
289
428
  updatecmd.add_argument("-d", "--data", required=True)
@@ -306,7 +445,9 @@ def main() -> int:
306
445
  mkdir(config_basepath)
307
446
 
308
447
  if args.command == "config":
309
- run_config(config_filename, args.context, args.baseurl, args.username, args.password)
448
+ run_config(
449
+ config_filename, args.context, args.baseurl, args.username, args.password, args.current
450
+ )
310
451
  return 0
311
452
 
312
453
  if not isfile(config_filename):
@@ -327,8 +468,7 @@ def main() -> int:
327
468
  output(response.json())
328
469
  return 1
329
470
  except requests.exceptions.JSONDecodeError:
330
- output(
331
- error("Could not decode api response as JSON", "Could not decode"))
471
+ output(error("Could not decode api response as JSON", "Could not decode"))
332
472
  return 1
333
473
  headers = {"Authorization": "Bearer {}".format(token)}
334
474
 
@@ -346,20 +486,22 @@ def main() -> int:
346
486
  soa_url = setup_url(baseurl, None, None, zname, "SOA", None, args.zone)
347
487
  soa_json = run_list(soa_url, True, headers, ret=True)
348
488
  ttl = soa_json[0]["ttl"]
349
-
350
- try:
351
- url = setup_url(
352
- baseurl,
353
- args.argument,
354
- args.data,
355
- args.name,
356
- args.rtype,
357
- ttl,
358
- args.zone,
359
- )
360
- except AttributeError:
361
- parser.print_help(sys.stderr)
362
- return 1
489
+ elif args.command in ["auditlog", "changelog"]:
490
+ pass
491
+ else:
492
+ try:
493
+ url = setup_url(
494
+ baseurl,
495
+ args.argument,
496
+ args.data,
497
+ args.name,
498
+ args.rtype,
499
+ ttl,
500
+ args.zone,
501
+ )
502
+ except AttributeError:
503
+ parser.print_help(sys.stderr)
504
+ return 1
363
505
 
364
506
  try:
365
507
  if args.command == "add":
@@ -370,9 +512,19 @@ def main() -> int:
370
512
  run_list(url, args.json, headers)
371
513
  elif args.command == "update":
372
514
  run_update(url, args.json, headers)
515
+ elif args.command == "auditlog":
516
+ url = baseurl + "/user/auditlog"
517
+ run_log(url, args.json, headers)
518
+ elif args.command == "changelog":
519
+ url = baseurl + f"/zones/changelog/{args.zone.rstrip('.')}"
520
+ run_log(url, args.json, headers)
521
+ else:
522
+ parser.print_help(sys.stderr)
523
+ return 1
524
+ except requests.exceptions.RequestException as e:
525
+ output(error(e, "Could not connect to server"))
373
526
  except (RequestsJSONDecodeError, SimplejsonJSONDecodeError):
374
- output(
375
- error("Could not decode api response as JSON", "Could not decode"))
527
+ output(error("Could not decode api response as JSON", "Could not decode"))
376
528
  return 0
377
529
 
378
530
 
@@ -0,0 +1,251 @@
1
+ Metadata-Version: 2.1
2
+ Name: knotctl
3
+ Version: 0.0.8
4
+ Summary: A CLI for knotapi.
5
+ Author-email: Micke Nordin <hej@mic.ke>
6
+ Requires-Python: >=3.9
7
+ Description-Content-Type: text/markdown
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Dist: argcomplete==2.0.0
12
+ Requires-Dist: pyyaml==6.0.1
13
+ Requires-Dist: requests==2.27.1
14
+ Requires-Dist: simplejson==3.17.6
15
+ Project-URL: Documentation, https://code.smolnet.org/micke/knotctl
16
+ Project-URL: Source, https://code.smolnet.org/micke/knotctl
17
+
18
+ # knotctl
19
+
20
+ This is a commandline tool for knotapi: https://gitlab.nic.cz/knot/knot-dns-rest
21
+
22
+ ## Build and install
23
+
24
+ To install using pip, run the following command in a virtual envrionment.
25
+
26
+ ```
27
+ python -m pip install "knotctl @ git+https://code.smolnet.org/micke/knotctl
28
+ ```
29
+
30
+ To build and install as a deb-package
31
+
32
+ ```
33
+ sudo apt install python3-stdeb
34
+ git clone https://code.smolnet.org/micke/knotctl
35
+ cd knotctl
36
+ python3 setup.py --command-packages=stdeb.command bdist_deb
37
+ sudo dpkg -i deb_dist/knotctl_*_all.deb
38
+ ```
39
+ A prebuilt deb-package is also available from the release page: https://code.smolnet.org/micke/knotctl/releases/
40
+
41
+ ## Shell completion
42
+
43
+ For bash: add this to .bashrc
44
+
45
+ ```
46
+ source <(knotctl completion)
47
+ ```
48
+
49
+ For fish, run:
50
+
51
+ ```
52
+ knotctl completion --shell fish > ~/.config/fish/completions/knotctl.fish
53
+ ```
54
+
55
+ For tcsh: add this to .cshrc
56
+
57
+ ```
58
+ complete "knotctl" 'p@*@`python-argcomplete-tcsh "knotctl"`@' ;
59
+ ```
60
+
61
+ For zsh: add this to .zshrc
62
+
63
+ ```
64
+ autoload -U bashcompinit
65
+ bashcompinit
66
+ source <(knotctl completion)
67
+ ```
68
+ ## Usage
69
+ ```
70
+ usage: knotctl [-h] [--json | --no-json]
71
+ {add,auditlog,changelog,completion,config,delete,list,update}
72
+ ...
73
+
74
+ Manage DNS records with knot dns rest api:
75
+ * https://gitlab.nic.cz/knot/knot-dns-rest
76
+
77
+ positional arguments:
78
+ {add,auditlog,changelog,completion,config,delete,list,update}
79
+
80
+ options:
81
+ -h, --help show this help message and exit
82
+ --json, --no-json
83
+
84
+ The Domain Name System specifies a database of information
85
+ elements for network resources. The types of information
86
+ elements are categorized and organized with a list of DNS
87
+ record types, the resource records (RRs). Each record has a
88
+ name, a type, an expiration time (time to live), and
89
+ type-specific data.
90
+
91
+ The following is a list of terms used in this program:
92
+ ----------------------------------------------------------------
93
+ | Vocabulary | Description |
94
+ ----------------------------------------------------------------
95
+ | zone | A DNS zone is a specific portion of the DNS |
96
+ | | namespace in the Domain Name System (DNS), |
97
+ | | which a specific organization or administrator |
98
+ | | manages. |
99
+ ----------------------------------------------------------------
100
+ | name | In the Internet, a domain name is a string that |
101
+ | | identifies a realm of administrative autonomy, |
102
+ | | authority or control. Domain names are often |
103
+ | | used to identify services provided through the |
104
+ | | Internet, such as websites, email services and |
105
+ | | more. |
106
+ ----------------------------------------------------------------
107
+ | rtype | A record type indicates the format of the data |
108
+ | | and it gives a hint of its intended use. For |
109
+ | | example, the A record is used to translate from |
110
+ | | a domain name to an IPv4 address, the NS record |
111
+ | | lists which name servers can answer lookups on |
112
+ | | a DNS zone, and the MX record specifies the |
113
+ | | mail server used to handle mail for a domain |
114
+ | | specified in an e-mail address. |
115
+ ----------------------------------------------------------------
116
+ | data | A records data is of type-specific relevance, |
117
+ | | such as the IP address for address records, or |
118
+ | | the priority and hostname for MX records. |
119
+ ----------------------------------------------------------------
120
+
121
+ This information was compiled from Wikipedia:
122
+ * https://en.wikipedia.org/wiki/DNS_zone
123
+ * https://en.wikipedia.org/wiki/Domain_Name_System
124
+ * https://en.wikipedia.org/wiki/Zone_file
125
+ ```
126
+
127
+ ### ADD
128
+
129
+ ```
130
+ usage: knotctl add [-h] -d DATA -n NAME -r RTYPE [-t TTL] -z ZONE
131
+
132
+ Add a new record to the zone.
133
+
134
+ options:
135
+ -h, --help show this help message and exit
136
+ -d DATA, --data DATA
137
+ -n NAME, --name NAME
138
+ -r RTYPE, --rtype RTYPE
139
+ -t TTL, --ttl TTL
140
+ -z ZONE, --zone ZONE
141
+ ```
142
+
143
+ ### COMPLETION
144
+
145
+ ```
146
+ usage: knotctl completion [-h] [-s SHELL]
147
+
148
+ Generate shell completion script.
149
+
150
+ options:
151
+ -h, --help show this help message and exit
152
+ -s SHELL, --shell SHELL
153
+ ```
154
+
155
+ ### AUDITLOG
156
+
157
+ ```
158
+ usage: knotctl auditlog [-h]
159
+
160
+ Audit the log file for errors.
161
+
162
+ options:
163
+ -h, --help show this help message and exit
164
+ ```
165
+
166
+ ### CHANGELOG
167
+
168
+ ```
169
+ usage: knotctl changelog [-h] -z ZONE
170
+
171
+ View the changelog of a zone.
172
+
173
+ options:
174
+ -h, --help show this help message and exit
175
+ -z ZONE, --zone ZONE
176
+ ```
177
+
178
+ ### CONFIG
179
+
180
+ ```
181
+ usage: knotctl config [-h] [-b BASEURL] [-c CONTEXT] [-p PASSWORD] [-u USERNAME]
182
+
183
+ Configure access to knot-dns-rest-api.
184
+
185
+ options:
186
+ -h, --help show this help message and exit
187
+ -b BASEURL, --baseurl BASEURL
188
+ -c CONTEXT, --context CONTEXT
189
+ -p PASSWORD, --password PASSWORD
190
+ -u USERNAME, --username USERNAME
191
+ ```
192
+
193
+ ### DELETE
194
+
195
+ ```
196
+ usage: knotctl delete [-h] [-d DATA] [-n NAME] [-r RTYPE] -z ZONE
197
+
198
+ Delete a record from the zone.
199
+
200
+ options:
201
+ -h, --help show this help message and exit
202
+ -d DATA, --data DATA
203
+ -n NAME, --name NAME
204
+ -r RTYPE, --rtype RTYPE
205
+ -z ZONE, --zone ZONE
206
+ ```
207
+
208
+ ### LIST
209
+
210
+ ```
211
+ usage: knotctl list [-h] [-d DATA] [-n NAME] [-r RTYPE] -z ZONE
212
+
213
+ List records in the zone.
214
+
215
+ options:
216
+ -h, --help show this help message and exit
217
+ -d DATA, --data DATA
218
+ -n NAME, --name NAME
219
+ -r RTYPE, --rtype RTYPE
220
+ -z ZONE, --zone ZONE
221
+ ```
222
+
223
+ ### UPDATE
224
+
225
+ ```
226
+ usage: knotctl update [-h] -a [ARGUMENT ...] -d DATA -n NAME -r RTYPE [-t TTL]
227
+ -z ZONE
228
+ Update a record in the zone. The record must exist in the zone.
229
+ In this case --data, --name, --rtype and --ttl switches are used
230
+ for searching for the appropriate record, while the --argument
231
+ switches are used for updating the record.
232
+
233
+ options:
234
+ -h, --help show this help message and exit
235
+ -a [KEY=VALUE ...], --argument [KEY=VALUE ...]
236
+ Specify key - value pairs to be updated:
237
+ name=dns1.example.com. or data=127.0.0.1 for example.
238
+ --argument can be repeated
239
+ -d DATA, --data DATA
240
+ -n NAME, --name NAME
241
+ -r RTYPE, --rtype RTYPE
242
+ -t TTL, --ttl TTL
243
+ -z ZONE, --zone ZONE
244
+
245
+ Available arguments are:
246
+ data: New record data.
247
+ name: New record domain name.
248
+ rtype: New record type.
249
+ ttl: New record time to live (TTL).
250
+ ```
251
+
@@ -0,0 +1,6 @@
1
+ knotctl/__init__.py,sha256=WkfcExtJNhEyRIuPXvepLaaD-XpW1rA6nl31fGxBinU,18430
2
+ knotctl-0.0.8.dist-info/entry_points.txt,sha256=oGFZaAfsfqC-KbiCm04W6DTBFCq2f5F_p3KMEgNoY4s,40
3
+ knotctl-0.0.8.dist-info/LICENSE,sha256=tqi_Y64slbCqJW7ndGgNe9GPIfRX2nVGb3YQs7FqzE4,34670
4
+ knotctl-0.0.8.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
5
+ knotctl-0.0.8.dist-info/METADATA,sha256=GgPeYTTKSoe6ONxgwF44fe85S6yHMnsBuWp7-y9rg4g,7236
6
+ knotctl-0.0.8.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: flit 3.8.0
2
+ Generator: flit 3.9.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,162 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: knotctl
3
- Version: 0.0.7
4
- Summary: A CLI for knotapi.
5
- Author-email: Micke Nordin <hej@mic.ke>
6
- Requires-Python: >=3.9
7
- Description-Content-Type: text/markdown
8
- Classifier: Programming Language :: Python :: 3
9
- Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
10
- Classifier: Operating System :: OS Independent
11
- Requires-Dist: argcomplete==2.0.0
12
- Requires-Dist: pyyaml==6.0.1
13
- Requires-Dist: requests==2.27.1
14
- Requires-Dist: simplejson==3.17.6
15
- Project-URL: Documentation, https://code.smolnet.org/micke/knotctl
16
- Project-URL: Source, https://code.smolnet.org/micke/knotctl
17
-
18
- # knotctl
19
-
20
- This is a commandline tool for knotapi: https://gitlab.nic.cz/knot/knot-dns-rest
21
-
22
- ## Build and install
23
-
24
- To install using pip, run the following command in a virtual envrionment.
25
-
26
- ```
27
- python -m pip install "knotctl @ git+https://code.smolnet.org/micke/knotctl
28
- ```
29
-
30
- To build and install as a deb-package
31
-
32
- ```
33
- sudo apt install python3-stdeb
34
- git clone https://code.smolnet.org/micke/knotctl
35
- cd knotctl
36
- python3 setup.py --command-packages=stdeb.command bdist_deb
37
- sudo dpkg -i deb_dist/knotctl_*_all.deb
38
- ```
39
- A prebuilt deb-package is also available from the release page: https://code.smolnet.org/micke/knotctl/releases/
40
-
41
- ## Shell completion
42
-
43
- For bash: add this to .bashrc
44
-
45
- ```
46
- source <(knotctl completion)
47
- ```
48
-
49
- For fish, run:
50
-
51
- ```
52
- knotctl completion --shell fish > ~/.config/fish/completions/knotctl.fish
53
- ```
54
-
55
- For tcsh: add this to .cshrc
56
-
57
- ```
58
- complete "knotctl" 'p@*@`python-argcomplete-tcsh "knotctl"`@' ;
59
- ```
60
-
61
- For zsh: add this to .zshrc
62
-
63
- ```
64
- autoload -U bashcompinit
65
- bashcompinit
66
- source <(knotctl completion)
67
- ```
68
- ## Usage
69
-
70
- ```
71
- usage: knotctl [-h] [--json | --no-json]
72
- {add,completion,config,delete,list,update} ...
73
-
74
- positional arguments:
75
- {add,completion,config,delete,list,update}
76
-
77
- options:
78
- -h, --help show this help message and exit
79
- --json, --no-json
80
- ```
81
-
82
- ### ADD
83
-
84
- ```
85
- usage: knotctl add [-h] -d DATA -n NAME -r RTYPE [-t TTL] -z ZONE
86
-
87
- options:
88
- -h, --help show this help message and exit
89
- -d DATA, --data DATA
90
- -n NAME, --name NAME
91
- -r RTYPE, --rtype RTYPE
92
- -t TTL, --ttl TTL
93
- -z ZONE, --zone ZONE
94
- ```
95
-
96
- ### COMPLETION
97
-
98
- ```
99
- usage: knotctl completion [-h] [-s SHELL]
100
-
101
- options:
102
- -h, --help show this help message and exit
103
- -s SHELL, --shell SHELL
104
- ```
105
-
106
- ### CONFIG
107
-
108
- ```
109
- usage: knotctl config [-h] [-c CONTEXT] [-b BASEURL] [-p PASSWORD] [-u USERNAME]
110
-
111
- options:
112
- -h, --help show this help message and exit
113
- -c CONTEXT, --context CONTEXT
114
- -b BASEURL, --baseurl BASEURL
115
- -p PASSWORD, --password PASSWORD
116
- -u USERNAME, --username USERNAME
117
- ```
118
-
119
- ### DELETE
120
-
121
- ```
122
- usage: knotctl delete [-h] [-d DATA] [-n NAME] [-r RTYPE] -z ZONE
123
-
124
- options:
125
- -h, --help show this help message and exit
126
- -d DATA, --data DATA
127
- -n NAME, --name NAME
128
- -r RTYPE, --rtype RTYPE
129
- -z ZONE, --zone ZONE
130
- ```
131
-
132
- ### LIST
133
-
134
- ```
135
- usage: knotctl list [-h] [-d DATA] [-n NAME] [-r RTYPE] [-z ZONE]
136
-
137
- options:
138
- -h, --help show this help message and exit
139
- -d DATA, --data DATA
140
- -n NAME, --name NAME
141
- -r RTYPE, --rtype RTYPE
142
- -z ZONE, --zone ZONE
143
- ```
144
-
145
- ### UPDATE
146
-
147
- ```
148
- usage: knotctl update [-h] -a [ARGUMENT ...] -d DATA -n NAME -r RTYPE [-t TTL]
149
- -z ZONE
150
-
151
- options:
152
- -h, --help show this help message and exit
153
- -a [ARGUMENT ...], --argument [ARGUMENT ...]
154
- Specify key - value pairs to be updated:
155
- name=dns1.example.com.
156
- -d DATA, --data DATA
157
- -n NAME, --name NAME
158
- -r RTYPE, --rtype RTYPE
159
- -t TTL, --ttl TTL
160
- -z ZONE, --zone ZONE
161
- ```
162
-
@@ -1,6 +0,0 @@
1
- knotctl/__init__.py,sha256=QC1gkjDiBJkuxOAc7_cOzY4cSuxsRWX-QHEmDgdE8zM,11581
2
- knotctl-0.0.7.dist-info/entry_points.txt,sha256=oGFZaAfsfqC-KbiCm04W6DTBFCq2f5F_p3KMEgNoY4s,40
3
- knotctl-0.0.7.dist-info/LICENSE,sha256=tqi_Y64slbCqJW7ndGgNe9GPIfRX2nVGb3YQs7FqzE4,34670
4
- knotctl-0.0.7.dist-info/WHEEL,sha256=rSgq_JpHF9fHR1lx53qwg_1-2LypZE_qmcuXbVUq948,81
5
- knotctl-0.0.7.dist-info/METADATA,sha256=1fYARNDu5JMdBFEumodfhlLa7_6SfJJaJ4czUlAwiJI,3600
6
- knotctl-0.0.7.dist-info/RECORD,,