mreg-cli 1.0.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 (53) hide show
  1. mreg_cli/__about__.py +7 -0
  2. mreg_cli/__init__.py +5 -0
  3. mreg_cli/__main__.py +8 -0
  4. mreg_cli/_version.py +16 -0
  5. mreg_cli/api/__init__.py +7 -0
  6. mreg_cli/api/abstracts.py +486 -0
  7. mreg_cli/api/endpoints.py +130 -0
  8. mreg_cli/api/fields.py +104 -0
  9. mreg_cli/api/history.py +152 -0
  10. mreg_cli/api/models.py +3416 -0
  11. mreg_cli/cli.py +382 -0
  12. mreg_cli/commands/__init__.py +1 -0
  13. mreg_cli/commands/base.py +62 -0
  14. mreg_cli/commands/dhcp.py +136 -0
  15. mreg_cli/commands/group.py +326 -0
  16. mreg_cli/commands/help.py +77 -0
  17. mreg_cli/commands/host.py +54 -0
  18. mreg_cli/commands/host_submodules/__init__.py +28 -0
  19. mreg_cli/commands/host_submodules/a_aaaa.py +452 -0
  20. mreg_cli/commands/host_submodules/bacnet.py +126 -0
  21. mreg_cli/commands/host_submodules/cname.py +166 -0
  22. mreg_cli/commands/host_submodules/core.py +507 -0
  23. mreg_cli/commands/host_submodules/rr.py +973 -0
  24. mreg_cli/commands/label.py +146 -0
  25. mreg_cli/commands/logging.py +112 -0
  26. mreg_cli/commands/network.py +516 -0
  27. mreg_cli/commands/permission.py +202 -0
  28. mreg_cli/commands/policy.py +519 -0
  29. mreg_cli/commands/recording.py +59 -0
  30. mreg_cli/commands/registry.py +56 -0
  31. mreg_cli/commands/root.py +58 -0
  32. mreg_cli/commands/zone.py +288 -0
  33. mreg_cli/config.py +253 -0
  34. mreg_cli/errorbuilder.py +193 -0
  35. mreg_cli/exceptions.py +237 -0
  36. mreg_cli/help_formatter.py +38 -0
  37. mreg_cli/main.py +238 -0
  38. mreg_cli/outputmanager.py +466 -0
  39. mreg_cli/py.typed +0 -0
  40. mreg_cli/tags.txt +55 -0
  41. mreg_cli/tokenfile.py +89 -0
  42. mreg_cli/types.py +160 -0
  43. mreg_cli/utilities/__init__.py +5 -0
  44. mreg_cli/utilities/api.py +595 -0
  45. mreg_cli/utilities/shared.py +65 -0
  46. mreg_cli/utilities/validators.py +19 -0
  47. mreg_cli-1.0.0.dist-info/AUTHORS +12 -0
  48. mreg_cli-1.0.0.dist-info/LICENSE +674 -0
  49. mreg_cli-1.0.0.dist-info/METADATA +1079 -0
  50. mreg_cli-1.0.0.dist-info/RECORD +53 -0
  51. mreg_cli-1.0.0.dist-info/WHEEL +5 -0
  52. mreg_cli-1.0.0.dist-info/entry_points.txt +2 -0
  53. mreg_cli-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,326 @@
1
+ """Hostgroups commands for mreg_cli."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ from typing import Any
7
+
8
+ from mreg_cli.api.models import Host, HostGroup
9
+ from mreg_cli.commands.base import BaseCommand
10
+ from mreg_cli.commands.registry import CommandRegistry
11
+ from mreg_cli.exceptions import CreateError, DeleteError, EntityNotFound, ForceMissing
12
+ from mreg_cli.outputmanager import OutputManager
13
+ from mreg_cli.types import Flag
14
+
15
+ command_registry = CommandRegistry()
16
+
17
+
18
+ class GroupCommands(BaseCommand):
19
+ """Group commands for the CLI."""
20
+
21
+ def __init__(self, cli: Any) -> None:
22
+ """Initialize the group commands."""
23
+ super().__init__(cli, command_registry, "group", "Manage hostgroups.", "Manage hostgroups")
24
+
25
+
26
+ @command_registry.register_command(
27
+ prog="create",
28
+ description="Create a new host group",
29
+ short_desc="Create a new host group",
30
+ flags=[
31
+ Flag("name", description="Group name", metavar="NAME"),
32
+ Flag("description", description="Description", metavar="DESCRIPTION"),
33
+ ],
34
+ )
35
+ def create(args: argparse.Namespace) -> None:
36
+ """Create a new host group.
37
+
38
+ :param args: argparse.Namespace (name, description)
39
+ """
40
+ HostGroup.get_by_field_and_raise("name", args.name)
41
+ newgroup = HostGroup.create(params={"name": args.name, "description": args.description})
42
+ if not newgroup:
43
+ raise CreateError("Failed to create new group '{args.name}'")
44
+
45
+ OutputManager().add_ok(f"Created new group {newgroup.name}")
46
+
47
+
48
+ @command_registry.register_command(
49
+ prog="info",
50
+ description="Shows group info with description, member count and owner(s)",
51
+ short_desc="Group info",
52
+ flags=[
53
+ Flag("name", description="Group name", nargs="+", metavar="NAME"),
54
+ ],
55
+ )
56
+ def info(args: argparse.Namespace) -> None:
57
+ """Show host group info.
58
+
59
+ :param args: argparse.Namespace (name)
60
+ """
61
+ for name in args.name:
62
+ HostGroup.get_by_name_or_raise(name).output()
63
+
64
+
65
+ @command_registry.register_command(
66
+ prog="rename",
67
+ description="Rename a group",
68
+ short_desc="Rename a group",
69
+ flags=[
70
+ Flag("oldname", description="Existing name", metavar="OLDNAME"),
71
+ Flag("newname", description="New name", metavar="NEWNAME"),
72
+ ],
73
+ )
74
+ def rename(args: argparse.Namespace) -> None:
75
+ """Rename group.
76
+
77
+ :param args: argparse.Namespace (oldname, newname)
78
+ """
79
+ group = HostGroup.get_by_name_or_raise(args.oldname)
80
+ HostGroup.get_by_name_and_raise(args.newname)
81
+ group.rename(args.newname)
82
+ OutputManager().add_ok(f"Renamed group {args.oldname!r} to {args.newname!r}")
83
+
84
+
85
+ @command_registry.register_command(
86
+ prog="list",
87
+ description="List group members",
88
+ short_desc="List group members",
89
+ flags=[
90
+ Flag("name", description="Group name", metavar="NAME"),
91
+ Flag("-expand", description="Expand group members", action="store_true"),
92
+ ],
93
+ )
94
+ def group_list(args: argparse.Namespace) -> None:
95
+ """List group members.
96
+
97
+ :param args: argparse.Namespace (name, expand)
98
+ """
99
+ group = HostGroup.get_by_name_or_raise(args.name)
100
+ group.output_members(expand=args.expand)
101
+
102
+
103
+ @command_registry.register_command(
104
+ prog="delete",
105
+ description="Delete host group",
106
+ short_desc="Delete host group",
107
+ flags=[
108
+ Flag("name", description="Group name", metavar="NAME"),
109
+ Flag("-force", action="store_true", description="Enable force"),
110
+ ],
111
+ )
112
+ def group_delete(args: argparse.Namespace) -> None:
113
+ """Delete a host group.
114
+
115
+ :param args: argparse.Namespace (name, force)
116
+ """
117
+ group = HostGroup.get_by_name_or_raise(args.name)
118
+ if (group.hosts or group.groups) and not args.force:
119
+ raise ForceMissing("Group contains hosts or groups, must force")
120
+
121
+ if not group.delete():
122
+ raise DeleteError(f"Failed to delete group {args.name}")
123
+
124
+ OutputManager().add_ok(f"Deleted group {args.name!r}")
125
+
126
+
127
+ @command_registry.register_command(
128
+ prog="group_add",
129
+ description="Add source group(s) to destination group",
130
+ short_desc="Add group(s) to group",
131
+ flags=[
132
+ Flag("dstgroup", description="destination group", metavar="DSTGROUP"),
133
+ Flag("srcgroup", description="source group", nargs="+", metavar="SRCGROUP"),
134
+ ],
135
+ )
136
+ def group_add(args: argparse.Namespace) -> None:
137
+ """Add group(s) to group.
138
+
139
+ :param args: argparse.Namespace (dstgroup, srcgroup)
140
+ """
141
+ sourcegroups = [HostGroup.get_by_name_or_raise(name) for name in args.srcgroup]
142
+ destgroup = HostGroup.get_by_name_or_raise(args.dstgroup)
143
+
144
+ for src in sourcegroups:
145
+ destgroup.add_group(src.name)
146
+ OutputManager().add_ok(f"Added group {src.name!r} to {destgroup.name!r}")
147
+
148
+
149
+ @command_registry.register_command(
150
+ prog="group_remove",
151
+ description="Remove source group(s) from destination group",
152
+ short_desc="Remove group(s) from group",
153
+ flags=[
154
+ Flag("dstgroup", description="destination group", metavar="DSTGROUP"),
155
+ Flag("srcgroup", description="source group", nargs="+", metavar="SRCGROUP"),
156
+ ],
157
+ )
158
+ def group_remove(args: argparse.Namespace) -> None:
159
+ """Remove group(s) from group.
160
+
161
+ :param args: argparse.Namespace (dstgroup, srcgroup)
162
+ """
163
+ ownergroup = HostGroup.get_by_name_or_raise(args.dstgroup)
164
+
165
+ for name in args.srcgroup:
166
+ if not ownergroup.has_group(name):
167
+ raise EntityNotFound(f"Group {name!r} not a member in {ownergroup.name!r}")
168
+
169
+ for name in args.srcgroup:
170
+ ownergroup.remove_group(name)
171
+ OutputManager().add_ok(f"Removed group {name!r} from {ownergroup.name!r}")
172
+
173
+
174
+ @command_registry.register_command(
175
+ prog="host_add",
176
+ description="Add host(s) to group",
177
+ short_desc="Add host(s) to group",
178
+ flags=[
179
+ Flag("group", description="group", metavar="GROUP"),
180
+ Flag("hosts", description="hosts", nargs="+", metavar="HOST"),
181
+ ],
182
+ )
183
+ def host_add(args: argparse.Namespace) -> None:
184
+ """Add host(s) to group.
185
+
186
+ :param args: argparse.Namespace (group, hosts)
187
+ """
188
+ hostgroup = HostGroup.get_by_name_or_raise(args.group)
189
+
190
+ for name in args.hosts:
191
+ host = Host.get_by_any_means_or_raise(name)
192
+ fqname = host.name.hostname
193
+ hostgroup.add_host(fqname)
194
+ OutputManager().add_ok(f"Added host {fqname!r} to {args.group!r}")
195
+
196
+
197
+ @command_registry.register_command(
198
+ prog="host_remove",
199
+ description="Remove host(s) from group",
200
+ short_desc="Remove host(s) from group",
201
+ flags=[
202
+ Flag("group", description="group", metavar="GROUP"),
203
+ Flag("hosts", description="host", nargs="+", metavar="HOST"),
204
+ ],
205
+ )
206
+ def host_remove(args: argparse.Namespace) -> None:
207
+ """Remove host(s) from group.
208
+
209
+ :param args: argparse.Namespace (group, hosts)
210
+ """
211
+ hostgroup = HostGroup.get_by_name_or_raise(args.group)
212
+
213
+ to_remove: set[str] = set()
214
+ for name in args.hosts:
215
+ host = Host.get_by_any_means_or_raise(name)
216
+ fqname = host.name.hostname
217
+ if not hostgroup.has_host(fqname):
218
+ raise EntityNotFound(f"Host {name!r} ({fqname}) not a member in {args.group!r}")
219
+ to_remove.add(fqname)
220
+
221
+ for name in to_remove:
222
+ hostgroup.remove_host(name)
223
+ OutputManager().add_ok(f"Removed host {name!r} from {args.group!r}")
224
+
225
+
226
+ @command_registry.register_command(
227
+ prog="host_list",
228
+ description="List host's group memberships",
229
+ short_desc="List host's group memberships",
230
+ flags=[
231
+ Flag("host", description="hostname", metavar="HOST"),
232
+ Flag(
233
+ "-traverse-hostgroups",
234
+ action="store_true",
235
+ description="Show memberships of all parent groups as well as direct groups.",
236
+ short_desc="Traverse hostgroups.",
237
+ ),
238
+ ],
239
+ )
240
+ def host_list(args: argparse.Namespace) -> None:
241
+ """List group memberships for host.
242
+
243
+ :param args: argparse.Namespace (host, traverse-hostgroups)
244
+ """
245
+ host = Host.get_by_any_means_or_raise(args.host)
246
+ HostGroup.output_multiple(host.hostgroups(traverse=args.traverse_hostgroups), multiline=True)
247
+
248
+
249
+ @command_registry.register_command(
250
+ prog="owner_add",
251
+ description="Add owner(s) to group",
252
+ short_desc="Add owner(s) to group",
253
+ flags=[
254
+ Flag("group", description="group", metavar="GROUP"),
255
+ Flag("owners", description="owners", nargs="+", metavar="OWNER"),
256
+ ],
257
+ )
258
+ def owner_add(args: argparse.Namespace) -> None:
259
+ """Add owner(s) to group.
260
+
261
+ :param args: argparse.Namespace (group, owners)
262
+ """
263
+ hostgroup = HostGroup.get_by_name_or_raise(args.group)
264
+
265
+ for name in args.owners:
266
+ hostgroup.add_owner(name)
267
+ OutputManager().add_ok(f"Added owner {name!r} to {args.group!r}")
268
+
269
+
270
+ @command_registry.register_command(
271
+ prog="owner_remove",
272
+ description="Remove owner(s) from group",
273
+ short_desc="Remove owner(s) from group",
274
+ flags=[
275
+ Flag("group", description="group", metavar="GROUP"),
276
+ Flag("owners", description="owner", nargs="+", metavar="OWNER"),
277
+ ],
278
+ )
279
+ def owner_remove(args: argparse.Namespace) -> None:
280
+ """Remove owner(s) from group.
281
+
282
+ :param args: argparse.Namespace (group, owners)
283
+ """
284
+ hostgroup = HostGroup.get_by_name_or_raise(args.group)
285
+
286
+ for name in args.owners:
287
+ if not hostgroup.has_owner(name):
288
+ raise EntityNotFound(f"Owner {name!r} not a member in {args.group!r}")
289
+
290
+ for name in args.owners:
291
+ hostgroup.remove_owner(name)
292
+ OutputManager().add_ok(f"Removed owner {name!r} from {args.group!r}")
293
+
294
+
295
+ @command_registry.register_command(
296
+ prog="set_description",
297
+ description="Set description for group",
298
+ short_desc="Set description for group",
299
+ flags=[
300
+ Flag("name", description="Group", metavar="GROUP"),
301
+ Flag("description", description="Group description.", metavar="DESC"),
302
+ ],
303
+ )
304
+ def set_description(args: argparse.Namespace) -> None:
305
+ """Set description for group.
306
+
307
+ :param args: argparse.Namespace (name, description)
308
+ """
309
+ HostGroup.get_by_name_or_raise(args.name).set_description(args.description)
310
+ OutputManager().add_ok(f"Updated description to {args.description!r} for {args.name!r}")
311
+
312
+
313
+ @command_registry.register_command(
314
+ prog="history",
315
+ description="Show history for group name",
316
+ short_desc="Show history for group name",
317
+ flags=[
318
+ Flag("name", description="Group name", metavar="NAME"),
319
+ ],
320
+ )
321
+ def history(args: argparse.Namespace) -> None:
322
+ """Show host history for name.
323
+
324
+ :param args: argparse.Namespace (name)
325
+ """
326
+ HostGroup.output_history(args.name)
@@ -0,0 +1,77 @@
1
+ """Help command for the CLI."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ from typing import Any
7
+
8
+ from mreg_cli.commands.base import BaseCommand
9
+ from mreg_cli.commands.registry import CommandRegistry
10
+ from mreg_cli.config import MregCliConfig
11
+
12
+ command_registry = CommandRegistry()
13
+
14
+
15
+ class HelpCommands(BaseCommand):
16
+ """Help commands for the CLI."""
17
+
18
+ def __init__(self, cli: Any) -> None:
19
+ """Initialize the help commands."""
20
+ super().__init__(
21
+ cli,
22
+ command_registry,
23
+ "help",
24
+ "Show general help for the cli. Use `help -h` to see subtopics.",
25
+ "Help",
26
+ callback=lambda _: cli.parser.print_help(),
27
+ )
28
+
29
+
30
+ @command_registry.register_command("filtering", "Show help for filtering.", "Filtering Help")
31
+ def filtering_help(_: argparse.Namespace) -> None:
32
+ """Show help for filtering."""
33
+ print(
34
+ """`mreg-cli` support output filtering via the operators `|` and `|!`.
35
+
36
+ The `|` operator is used to filter the output to only render the lines
37
+ matching the regular expression specified after the operator. Using `|!`
38
+ will show the lines _not_ matching.
39
+
40
+ Note that if recording to a file, filters will be applied to the output
41
+ as it would be to the terminal.
42
+
43
+ Some examples:
44
+
45
+ # No filtering
46
+ mreg> host info one.example.com
47
+ Name: one.example.com
48
+ Contact: me@example.com
49
+ A_Records IP MAC
50
+ 192.168.1.2 aa:bb:cc:dd:ee:ff
51
+ TTL: (Default)
52
+ TXT: v=spf1 -all
53
+
54
+ # Filter to only show lines containing "example"
55
+ mreg> host info one.example.com | example
56
+ Name: one.example.com
57
+ Contact: me@example.com
58
+
59
+ # Filter to only show lines containing "me" followed by "com"
60
+ mreg> host info one.example.com | me.*com
61
+ Contact: me@example.com
62
+
63
+ # Filter to only show lines _not_ containing "me" followed by "com"
64
+ mreg> host info one.example.com |! me.*com
65
+ Name: one.example.com
66
+ A_Records IP MAC
67
+ 192.168.1.2 aa:bb:cc:dd:ee:ff
68
+ TTL: (Default)
69
+ TXT: v=spf1 -all
70
+ """
71
+ )
72
+
73
+
74
+ @command_registry.register_command("configuration", "Show configuration", "Show configuration")
75
+ def configuration_help(_: argparse.Namespace) -> None:
76
+ """Show configuration."""
77
+ MregCliConfig().print_config_table()
@@ -0,0 +1,54 @@
1
+ """The base host command module.
2
+
3
+ There are a huge amount of commands in this module, so it is broken up into
4
+ submodules. This base module contains the registry that the submodules
5
+ add their commands to.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import importlib
11
+ import os
12
+ import pkgutil
13
+ from typing import Any
14
+
15
+ from mreg_cli.commands.base import BaseCommand
16
+ from mreg_cli.commands.registry import CommandRegistry
17
+ from mreg_cli.exceptions import InternalError
18
+
19
+ registry = CommandRegistry()
20
+
21
+
22
+ class HostCommands(BaseCommand):
23
+ """Host command module to register all subcommands."""
24
+
25
+ def __init__(self, cli: Any) -> None:
26
+ """Initialize the Host commands."""
27
+ super().__init__(cli, registry, "host", "Manage Hosts.", "Host Management")
28
+
29
+ # This is a class method that overrides the inherited method in a rather
30
+ # hacky way. The reason for this is that the host class is large enough
31
+ # that it is broken up into submodules, and each submodule registers its
32
+ # commands with the host class. This is done by importing the command
33
+ # registry directly from the host command module.
34
+ # The current design avoids circular imports, and removes the need to
35
+ # explicitly import each submodule by name in this scope.
36
+ def register_all_commands(self) -> None:
37
+ """Register all host subcommands from different modules."""
38
+ self._import_submodules()
39
+ super().register_all_commands()
40
+
41
+ def _import_submodules(self) -> None:
42
+ """Dynamically import all submodules in the host_submodules package."""
43
+ package_name = "mreg_cli.commands.host_submodules"
44
+ package = importlib.import_module(package_name)
45
+
46
+ # Get the directory path of the package
47
+ if package.__file__ is None:
48
+ raise InternalError(f"Unable to initalize host submodules from {package_name}")
49
+
50
+ package_dir = os.path.dirname(package.__file__)
51
+
52
+ # Import all submodules
53
+ for _, module_name, _ in pkgutil.iter_modules([package_dir]):
54
+ importlib.import_module(f"{package_name}.{module_name}")
@@ -0,0 +1,28 @@
1
+ """Submodules for the host command.
2
+
3
+ The host command has a lot of subcommands, so they are broken up into
4
+ submodules. Each of these modules registers their commands with the
5
+ :py:class:`mreg_cli.commands.host.HostCommands` class, which is the main
6
+ command class for the host command.
7
+
8
+ This is done by importing the command registry directly from the host
9
+ command module, which is a bit hacky, but it works.
10
+
11
+ Note: This design will imply circular imports, so the core host command
12
+ imports the submodules after it has been initialized.
13
+ """
14
+
15
+ # We have to import each of the submodules explictly here in order to
16
+ # ensure they are included when we build binaries with PyInstaller.
17
+ # We also cannot do `from . import *`. Each module must be specified.
18
+ from __future__ import annotations
19
+
20
+ from . import a_aaaa, bacnet, cname, core, rr
21
+
22
+ __all__ = [
23
+ "a_aaaa",
24
+ "bacnet",
25
+ "cname",
26
+ "core",
27
+ "rr",
28
+ ]