knotctl 0.0.7__tar.gz → 0.0.9__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.
knotctl-0.0.9/PKG-INFO ADDED
@@ -0,0 +1,251 @@
1
+ Metadata-Version: 2.1
2
+ Name: knotctl
3
+ Version: 0.0.9
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,233 @@
1
+ # knotctl
2
+
3
+ This is a commandline tool for knotapi: https://gitlab.nic.cz/knot/knot-dns-rest
4
+
5
+ ## Build and install
6
+
7
+ To install using pip, run the following command in a virtual envrionment.
8
+
9
+ ```
10
+ python -m pip install "knotctl @ git+https://code.smolnet.org/micke/knotctl
11
+ ```
12
+
13
+ To build and install as a deb-package
14
+
15
+ ```
16
+ sudo apt install python3-stdeb
17
+ git clone https://code.smolnet.org/micke/knotctl
18
+ cd knotctl
19
+ python3 setup.py --command-packages=stdeb.command bdist_deb
20
+ sudo dpkg -i deb_dist/knotctl_*_all.deb
21
+ ```
22
+ A prebuilt deb-package is also available from the release page: https://code.smolnet.org/micke/knotctl/releases/
23
+
24
+ ## Shell completion
25
+
26
+ For bash: add this to .bashrc
27
+
28
+ ```
29
+ source <(knotctl completion)
30
+ ```
31
+
32
+ For fish, run:
33
+
34
+ ```
35
+ knotctl completion --shell fish > ~/.config/fish/completions/knotctl.fish
36
+ ```
37
+
38
+ For tcsh: add this to .cshrc
39
+
40
+ ```
41
+ complete "knotctl" 'p@*@`python-argcomplete-tcsh "knotctl"`@' ;
42
+ ```
43
+
44
+ For zsh: add this to .zshrc
45
+
46
+ ```
47
+ autoload -U bashcompinit
48
+ bashcompinit
49
+ source <(knotctl completion)
50
+ ```
51
+ ## Usage
52
+ ```
53
+ usage: knotctl [-h] [--json | --no-json]
54
+ {add,auditlog,changelog,completion,config,delete,list,update}
55
+ ...
56
+
57
+ Manage DNS records with knot dns rest api:
58
+ * https://gitlab.nic.cz/knot/knot-dns-rest
59
+
60
+ positional arguments:
61
+ {add,auditlog,changelog,completion,config,delete,list,update}
62
+
63
+ options:
64
+ -h, --help show this help message and exit
65
+ --json, --no-json
66
+
67
+ The Domain Name System specifies a database of information
68
+ elements for network resources. The types of information
69
+ elements are categorized and organized with a list of DNS
70
+ record types, the resource records (RRs). Each record has a
71
+ name, a type, an expiration time (time to live), and
72
+ type-specific data.
73
+
74
+ The following is a list of terms used in this program:
75
+ ----------------------------------------------------------------
76
+ | Vocabulary | Description |
77
+ ----------------------------------------------------------------
78
+ | zone | A DNS zone is a specific portion of the DNS |
79
+ | | namespace in the Domain Name System (DNS), |
80
+ | | which a specific organization or administrator |
81
+ | | manages. |
82
+ ----------------------------------------------------------------
83
+ | name | In the Internet, a domain name is a string that |
84
+ | | identifies a realm of administrative autonomy, |
85
+ | | authority or control. Domain names are often |
86
+ | | used to identify services provided through the |
87
+ | | Internet, such as websites, email services and |
88
+ | | more. |
89
+ ----------------------------------------------------------------
90
+ | rtype | A record type indicates the format of the data |
91
+ | | and it gives a hint of its intended use. For |
92
+ | | example, the A record is used to translate from |
93
+ | | a domain name to an IPv4 address, the NS record |
94
+ | | lists which name servers can answer lookups on |
95
+ | | a DNS zone, and the MX record specifies the |
96
+ | | mail server used to handle mail for a domain |
97
+ | | specified in an e-mail address. |
98
+ ----------------------------------------------------------------
99
+ | data | A records data is of type-specific relevance, |
100
+ | | such as the IP address for address records, or |
101
+ | | the priority and hostname for MX records. |
102
+ ----------------------------------------------------------------
103
+
104
+ This information was compiled from Wikipedia:
105
+ * https://en.wikipedia.org/wiki/DNS_zone
106
+ * https://en.wikipedia.org/wiki/Domain_Name_System
107
+ * https://en.wikipedia.org/wiki/Zone_file
108
+ ```
109
+
110
+ ### ADD
111
+
112
+ ```
113
+ usage: knotctl add [-h] -d DATA -n NAME -r RTYPE [-t TTL] -z ZONE
114
+
115
+ Add a new record to the zone.
116
+
117
+ options:
118
+ -h, --help show this help message and exit
119
+ -d DATA, --data DATA
120
+ -n NAME, --name NAME
121
+ -r RTYPE, --rtype RTYPE
122
+ -t TTL, --ttl TTL
123
+ -z ZONE, --zone ZONE
124
+ ```
125
+
126
+ ### COMPLETION
127
+
128
+ ```
129
+ usage: knotctl completion [-h] [-s SHELL]
130
+
131
+ Generate shell completion script.
132
+
133
+ options:
134
+ -h, --help show this help message and exit
135
+ -s SHELL, --shell SHELL
136
+ ```
137
+
138
+ ### AUDITLOG
139
+
140
+ ```
141
+ usage: knotctl auditlog [-h]
142
+
143
+ Audit the log file for errors.
144
+
145
+ options:
146
+ -h, --help show this help message and exit
147
+ ```
148
+
149
+ ### CHANGELOG
150
+
151
+ ```
152
+ usage: knotctl changelog [-h] -z ZONE
153
+
154
+ View the changelog of a zone.
155
+
156
+ options:
157
+ -h, --help show this help message and exit
158
+ -z ZONE, --zone ZONE
159
+ ```
160
+
161
+ ### CONFIG
162
+
163
+ ```
164
+ usage: knotctl config [-h] [-b BASEURL] [-c CONTEXT] [-p PASSWORD] [-u USERNAME]
165
+
166
+ Configure access to knot-dns-rest-api.
167
+
168
+ options:
169
+ -h, --help show this help message and exit
170
+ -b BASEURL, --baseurl BASEURL
171
+ -c CONTEXT, --context CONTEXT
172
+ -p PASSWORD, --password PASSWORD
173
+ -u USERNAME, --username USERNAME
174
+ ```
175
+
176
+ ### DELETE
177
+
178
+ ```
179
+ usage: knotctl delete [-h] [-d DATA] [-n NAME] [-r RTYPE] -z ZONE
180
+
181
+ Delete a record from the zone.
182
+
183
+ options:
184
+ -h, --help show this help message and exit
185
+ -d DATA, --data DATA
186
+ -n NAME, --name NAME
187
+ -r RTYPE, --rtype RTYPE
188
+ -z ZONE, --zone ZONE
189
+ ```
190
+
191
+ ### LIST
192
+
193
+ ```
194
+ usage: knotctl list [-h] [-d DATA] [-n NAME] [-r RTYPE] -z ZONE
195
+
196
+ List records in the zone.
197
+
198
+ options:
199
+ -h, --help show this help message and exit
200
+ -d DATA, --data DATA
201
+ -n NAME, --name NAME
202
+ -r RTYPE, --rtype RTYPE
203
+ -z ZONE, --zone ZONE
204
+ ```
205
+
206
+ ### UPDATE
207
+
208
+ ```
209
+ usage: knotctl update [-h] -a [ARGUMENT ...] -d DATA -n NAME -r RTYPE [-t TTL]
210
+ -z ZONE
211
+ Update a record in the zone. The record must exist in the zone.
212
+ In this case --data, --name, --rtype and --ttl switches are used
213
+ for searching for the appropriate record, while the --argument
214
+ switches are used for updating the record.
215
+
216
+ options:
217
+ -h, --help show this help message and exit
218
+ -a [KEY=VALUE ...], --argument [KEY=VALUE ...]
219
+ Specify key - value pairs to be updated:
220
+ name=dns1.example.com. or data=127.0.0.1 for example.
221
+ --argument can be repeated
222
+ -d DATA, --data DATA
223
+ -n NAME, --name NAME
224
+ -r RTYPE, --rtype RTYPE
225
+ -t TTL, --ttl TTL
226
+ -z ZONE, --zone ZONE
227
+
228
+ Available arguments are:
229
+ data: New record data.
230
+ name: New record domain name.
231
+ rtype: New record type.
232
+ ttl: New record time to live (TTL).
233
+ ```
@@ -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
+ if 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
 
@@ -16,7 +16,7 @@ classifiers=[
16
16
  "Operating System :: OS Independent",
17
17
  ]
18
18
  requires-python= ">=3.9"
19
- version = "0.0.7"
19
+ version = "0.0.9"
20
20
 
21
21
  dependencies = [
22
22
  "argcomplete==2.0.0",
knotctl-0.0.7/.gitignore DELETED
@@ -1,162 +0,0 @@
1
- # ---> Python
2
- # Byte-compiled / optimized / DLL files
3
- __pycache__/
4
- *.py[cod]
5
- *$py.class
6
-
7
- # C extensions
8
- *.so
9
-
10
- # Distribution / packaging
11
- .Python
12
- build/
13
- develop-eggs/
14
- dist/
15
- downloads/
16
- eggs/
17
- .eggs/
18
- lib/
19
- lib64/
20
- parts/
21
- sdist/
22
- var/
23
- wheels/
24
- share/python-wheels/
25
- *.egg-info/
26
- .installed.cfg
27
- *.egg
28
- MANIFEST
29
-
30
- # PyInstaller
31
- # Usually these files are written by a python script from a template
32
- # before PyInstaller builds the exe, so as to inject date/other infos into it.
33
- *.manifest
34
- *.spec
35
-
36
- # Installer logs
37
- pip-log.txt
38
- pip-delete-this-directory.txt
39
-
40
- # Unit test / coverage reports
41
- htmlcov/
42
- .tox/
43
- .nox/
44
- .coverage
45
- .coverage.*
46
- .cache
47
- nosetests.xml
48
- coverage.xml
49
- *.cover
50
- *.py,cover
51
- .hypothesis/
52
- .pytest_cache/
53
- cover/
54
-
55
- # Translations
56
- *.mo
57
- *.pot
58
-
59
- # Django stuff:
60
- *.log
61
- local_settings.py
62
- db.sqlite3
63
- db.sqlite3-journal
64
-
65
- # Flask stuff:
66
- instance/
67
- .webassets-cache
68
-
69
- # Scrapy stuff:
70
- .scrapy
71
-
72
- # Sphinx documentation
73
- docs/_build/
74
-
75
- # PyBuilder
76
- .pybuilder/
77
- target/
78
-
79
- # Jupyter Notebook
80
- .ipynb_checkpoints
81
-
82
- # IPython
83
- profile_default/
84
- ipython_config.py
85
-
86
- # pyenv
87
- # For a library or package, you might want to ignore these files since the code is
88
- # intended to run in multiple environments; otherwise, check them in:
89
- # .python-version
90
-
91
- # pipenv
92
- # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
93
- # However, in case of collaboration, if having platform-specific dependencies or dependencies
94
- # having no cross-platform support, pipenv may install dependencies that don't work, or not
95
- # install all needed dependencies.
96
- #Pipfile.lock
97
-
98
- # poetry
99
- # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
100
- # This is especially recommended for binary packages to ensure reproducibility, and is more
101
- # commonly ignored for libraries.
102
- # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
103
- #poetry.lock
104
-
105
- # pdm
106
- # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
107
- #pdm.lock
108
- # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
109
- # in version control.
110
- # https://pdm.fming.dev/#use-with-ide
111
- .pdm.toml
112
-
113
- # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
114
- __pypackages__/
115
-
116
- # Celery stuff
117
- celerybeat-schedule
118
- celerybeat.pid
119
-
120
- # SageMath parsed files
121
- *.sage.py
122
-
123
- # Environments
124
- .env
125
- .venv
126
- env/
127
- venv/
128
- ENV/
129
- env.bak/
130
- venv.bak/
131
-
132
- # Spyder project settings
133
- .spyderproject
134
- .spyproject
135
-
136
- # Rope project settings
137
- .ropeproject
138
-
139
- # mkdocs documentation
140
- /site
141
-
142
- # mypy
143
- .mypy_cache/
144
- .dmypy.json
145
- dmypy.json
146
-
147
- # Pyre type checker
148
- .pyre/
149
-
150
- # pytype static type analyzer
151
- .pytype/
152
-
153
- # Cython debug symbols
154
- cython_debug/
155
-
156
- # PyCharm
157
- # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
158
- # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
159
- # and can be added to the global gitignore or merged into this file. For a more nuclear
160
- # option (not recommended) you can uncomment the following to ignore the entire idea folder.
161
- #.idea/
162
-
knotctl-0.0.7/PKG-INFO DELETED
@@ -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
-
knotctl-0.0.7/README.md DELETED
@@ -1,144 +0,0 @@
1
- # knotctl
2
-
3
- This is a commandline tool for knotapi: https://gitlab.nic.cz/knot/knot-dns-rest
4
-
5
- ## Build and install
6
-
7
- To install using pip, run the following command in a virtual envrionment.
8
-
9
- ```
10
- python -m pip install "knotctl @ git+https://code.smolnet.org/micke/knotctl
11
- ```
12
-
13
- To build and install as a deb-package
14
-
15
- ```
16
- sudo apt install python3-stdeb
17
- git clone https://code.smolnet.org/micke/knotctl
18
- cd knotctl
19
- python3 setup.py --command-packages=stdeb.command bdist_deb
20
- sudo dpkg -i deb_dist/knotctl_*_all.deb
21
- ```
22
- A prebuilt deb-package is also available from the release page: https://code.smolnet.org/micke/knotctl/releases/
23
-
24
- ## Shell completion
25
-
26
- For bash: add this to .bashrc
27
-
28
- ```
29
- source <(knotctl completion)
30
- ```
31
-
32
- For fish, run:
33
-
34
- ```
35
- knotctl completion --shell fish > ~/.config/fish/completions/knotctl.fish
36
- ```
37
-
38
- For tcsh: add this to .cshrc
39
-
40
- ```
41
- complete "knotctl" 'p@*@`python-argcomplete-tcsh "knotctl"`@' ;
42
- ```
43
-
44
- For zsh: add this to .zshrc
45
-
46
- ```
47
- autoload -U bashcompinit
48
- bashcompinit
49
- source <(knotctl completion)
50
- ```
51
- ## Usage
52
-
53
- ```
54
- usage: knotctl [-h] [--json | --no-json]
55
- {add,completion,config,delete,list,update} ...
56
-
57
- positional arguments:
58
- {add,completion,config,delete,list,update}
59
-
60
- options:
61
- -h, --help show this help message and exit
62
- --json, --no-json
63
- ```
64
-
65
- ### ADD
66
-
67
- ```
68
- usage: knotctl add [-h] -d DATA -n NAME -r RTYPE [-t TTL] -z ZONE
69
-
70
- options:
71
- -h, --help show this help message and exit
72
- -d DATA, --data DATA
73
- -n NAME, --name NAME
74
- -r RTYPE, --rtype RTYPE
75
- -t TTL, --ttl TTL
76
- -z ZONE, --zone ZONE
77
- ```
78
-
79
- ### COMPLETION
80
-
81
- ```
82
- usage: knotctl completion [-h] [-s SHELL]
83
-
84
- options:
85
- -h, --help show this help message and exit
86
- -s SHELL, --shell SHELL
87
- ```
88
-
89
- ### CONFIG
90
-
91
- ```
92
- usage: knotctl config [-h] [-c CONTEXT] [-b BASEURL] [-p PASSWORD] [-u USERNAME]
93
-
94
- options:
95
- -h, --help show this help message and exit
96
- -c CONTEXT, --context CONTEXT
97
- -b BASEURL, --baseurl BASEURL
98
- -p PASSWORD, --password PASSWORD
99
- -u USERNAME, --username USERNAME
100
- ```
101
-
102
- ### DELETE
103
-
104
- ```
105
- usage: knotctl delete [-h] [-d DATA] [-n NAME] [-r RTYPE] -z ZONE
106
-
107
- options:
108
- -h, --help show this help message and exit
109
- -d DATA, --data DATA
110
- -n NAME, --name NAME
111
- -r RTYPE, --rtype RTYPE
112
- -z ZONE, --zone ZONE
113
- ```
114
-
115
- ### LIST
116
-
117
- ```
118
- usage: knotctl list [-h] [-d DATA] [-n NAME] [-r RTYPE] [-z ZONE]
119
-
120
- options:
121
- -h, --help show this help message and exit
122
- -d DATA, --data DATA
123
- -n NAME, --name NAME
124
- -r RTYPE, --rtype RTYPE
125
- -z ZONE, --zone ZONE
126
- ```
127
-
128
- ### UPDATE
129
-
130
- ```
131
- usage: knotctl update [-h] -a [ARGUMENT ...] -d DATA -n NAME -r RTYPE [-t TTL]
132
- -z ZONE
133
-
134
- options:
135
- -h, --help show this help message and exit
136
- -a [ARGUMENT ...], --argument [ARGUMENT ...]
137
- Specify key - value pairs to be updated:
138
- name=dns1.example.com.
139
- -d DATA, --data DATA
140
- -n NAME, --name NAME
141
- -r RTYPE, --rtype RTYPE
142
- -t TTL, --ttl TTL
143
- -z ZONE, --zone ZONE
144
- ```
@@ -1,4 +0,0 @@
1
- argcomplete==2.0.0
2
- pyyaml==6.0.1
3
- requests==2.27.1
4
- simplejson==3.17.6
knotctl-0.0.7/stdeb.cfg DELETED
@@ -1,4 +0,0 @@
1
- [DEFAULT]
2
- Depends3: python3-argcomplete, python3-requests, python3-simplejson, python3-yaml
3
- Debian-Version: 1
4
- Package3: knotctl
File without changes