]> mj.ucw.cz Git - pynsc.git/blob - nsconfig/cli.py
Improve status command
[pynsc.git] / nsconfig / cli.py
1 import argparse
2 from argparse import Namespace
3 from pathlib import Path
4 from texttable import Texttable
5
6 from nsconfig.core import Nsc, NscZonePrimary, NscZoneSecondary, NscZoneAlias
7
8
9 def do_test(nsc: Nsc) -> None:
10     test_dir = Path('test')
11     test_dir.mkdir(exist_ok=True)
12     for z in nsc.get_zones():
13         print(f'Zone:        {z.name}')
14         print(f'Type:        {z.zone_type.name}')
15         if isinstance(z, NscZonePrimary):
16             if z.aliases:
17                 aliases = ' '.join([alias.name for alias in z.aliases])
18                 print(f'Aliases:     {aliases}')
19             print(f'Old serial:  {z.prev_state.serial}')
20             print(f'Old hash:    {z.prev_state.hash}')
21             print(f'New serial:  {z.state.serial}')
22             print(f'New hash:    {z.state.hash}')
23             out_file = test_dir / z.safe_name
24             print(f'Dumping to:  {out_file}')
25             with open(out_file, 'w') as f:
26                 z.dump(file=f)
27         elif isinstance(z, NscZoneSecondary):
28             print(f'Primary:     {z.primary_server}')
29         elif isinstance(z, NscZoneAlias):
30             print(f'Alias for:   {z.alias_for.name}')
31         print()
32
33     if nsc.daemon:
34         conf_file = test_dir / 'daemon.conf'
35         print(f'Dumping daemon config to {conf_file}')
36         with open(conf_file, 'w') as f:
37             nsc.daemon.dump_config(file=f)
38
39
40 def do_status(nsc: Nsc, args: Namespace) -> None:
41     table = Texttable(max_width=0)
42     table.header(['S', 'Zone', 'Type', 'Status'])
43     table.set_deco(Texttable.HEADER)
44
45     for z in nsc.get_zones():
46         if z.is_changed():
47             action = '*'
48         else:
49             action = ""
50         do_show = args.all
51         if isinstance(z, NscZonePrimary):
52             status = f'serial {z.prev_state.serial}'
53             if z.is_changed():
54                 status += f' -> {z.state.serial}'
55             do_show = True
56         elif isinstance(z, NscZoneSecondary):
57             status = f'from {z.primary_server}'
58         elif isinstance(z, NscZoneAlias):
59             status = f'to {z.alias_for.name}'
60         else:
61             raise NotImplementedError()
62         if do_show:
63             table.add_row([action, z.name, z.zone_type.name, status])
64
65     print(table.draw())
66
67
68 def do_update(nsc: Nsc) -> None:
69     nsc.daemon.write_config()
70
71     for z in nsc.get_zones():
72         if isinstance(z, NscZonePrimary) and z.is_changed():
73             print(f'Updating zone {z.name} (serial {z.state.serial})')
74             z.write_zone()
75             nsc.daemon.reload_zone(z)
76             for alias in z.aliases:
77                 nsc.daemon.reload_zone(z)
78             z.write_state()
79
80     nsc.daemon.reload_daemon()
81
82
83 def main(nsc: Nsc) -> None:
84     parser = argparse.ArgumentParser(description='Configure name server')
85     subparsers = parser.add_subparsers(help='action to perform', dest='action', required=True, metavar='ACTION')
86
87     test_parser = subparsers.add_parser('test', help='test new configuration', description='Test new configuration')
88
89     status_parser = subparsers.add_parser('status', help='list status of zones', description='List status of zones')
90     status_parser.add_argument('-a', '--all', default=False, action='store_true', help='show non-primary zones')
91
92     update_parser = subparsers.add_parser('update', help='update configuration', description='Update zone files and daemon configuration as needed')
93
94     args = parser.parse_args()
95
96     nsc.process()
97
98     if args.action == 'test':
99         do_test(nsc)
100     elif args.action == 'status':
101         do_status(nsc, args)
102     elif args.action == 'update':
103         do_update(nsc)