-
Notifications
You must be signed in to change notification settings - Fork 0
/
kube-dns-tool.py
executable file
·218 lines (179 loc) · 8.63 KB
/
kube-dns-tool.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
#!/usr/bin/python
import argparse
import json
import subprocess
import yaml
"""
a tool to operate the kube-dns ConfigMap in the kubernetes.
This tool is designed to the O&M operators to update the kube-dns ConfigMap.
"""
def dump_kube_dns_cm( kube_dns_cm_file = None ):
"""
dump the kube-dns ConfigMap and parse it as a dict object
Args:
kube_dns_cm_file - load the config map from file if this is set, otherwise get the kube-dns
ConfigMap with "kubectl get cm kube-dns -n kube-system -o yaml"
Return:
a python dict object
"""
if kube_dns_cm_file is not None:
with open( kube_dns_cm_file ) as fp:
return yaml.load( fp )
out = subprocess.check_output( ['kubectl', 'get', 'cm', 'kube-dns', '-n', 'kube-system', '-o', 'yaml'] )
return yaml.load( out )
def dump_kube_dns( args ):
"""
dump the kube-dns configmap and print it
"""
print subprocess.check_output( ['kubectl', 'get', 'cm', 'kube-dns', '-n', 'kube-system', '-o', 'yaml'] )
def list_upstreams( args ):
"""
list all upstream DNS servers
"""
kube_dns = dump_kube_dns_cm()
if 'data' in kube_dns and 'upstreamNameservers' in kube_dns['data']:
print ",".join( json.loads( kube_dns['data']['upstreamNameservers'] ) )
def update_kube_dns( kube_dns, dry_run ):
"""
update the kube-dns ConfigMap to the system
Args:
kube_dbns - a python dict object in format dumped by the dump_kube_dns_cm() method
dry_run - print the kube_dns in yaml format but not update to the system if it is True
"""
removed_metadata_fields = ['resourceVersion', 'selfLink', 'uid', 'creationTimestamp']
for field in removed_metadata_fields:
if field in kube_dns['metadata']: del kube_dns['metadata'][field]
r = yaml.dump( kube_dns, default_flow_style = False )
if dry_run:
print r
else:
p = subprocess.Popen( ['kubectl', 'apply', '-f', '-' ], stdin = subprocess.PIPE )
p.communicate( r )
def add_upstreams( args ):
"""
add some upstream DNS servers
"""
kube_dns = dump_kube_dns_cm( args.kube_dns_cm_file )
if 'data' not in kube_dns: kube_dns['data'] = {}
upstreamServers = json.loads( kube_dns['data']['upstreamNameservers'] ) if 'upstreamNameservers' in kube_dns['data'] else []
for server in args.upstreamServers:
if server not in upstreamServers:
upstreamServers.append( server )
if len( upstreamServers ) > 0:
kube_dns['data']['upstreamNameservers'] = json.dumps( upstreamServers )
update_kube_dns( kube_dns, args.dry_run )
def del_upstreams( args ):
"""
delete some upstream DNS servers
"""
kube_dns = dump_kube_dns_cm( args.kube_dns_cm_file )
if 'data' not in kube_dns or 'upstreamNameservers' not in kube_dns['data']:
return
upstreamServers = json.loads( kube_dns['data']['upstreamNameservers'] )
for server in args.upstreamServers:
upstreamServers.remove( server )
if len( upstreamServers ) <= 0:
del kube_dns['data']['upstreamNameservers']
else:
kube_dns['data']['upstreamNameservers'] = json.dumps( upstreamServers )
update_kube_dns( kube_dns, args.dry_run )
def list_stub_domains( args ):
"""
list all the stub domain DNS servers
"""
kube_dns = dump_kube_dns_cm( args.kube_dns_cm_file )
if 'data' not in kube_dns or 'stubDomains' not in kube_dns['data']:
return
stubDomains = json.loads( kube_dns['data']['stubDomains'] )
for domain in stubDomains:
print "%s:%s" % (domain, ",".join( stubDomains[domain] ) )
def parse_command_line_stub_domain( stubDomain ):
"""
parse the stubDomain in format "domain:dns-server-1,dns-server-2,...,dns-server-n"
Args:
stubDomain - stubdomain in format "domain:dns-server-1,dns-server-2,...,dns-server-n"
Returns:
a tuple with two elements:
- domain name
- a list of dns-server
"""
pos = stubDomain.find( ':' )
return stubDomain[0:pos], stubDomain[pos+1:].split(',') if pos > 0 else None
def add_stub_domains( args ):
"""
add the stub domains
"""
stubDomains = {}
for stubDomain in args.stubDomains:
domain, dns_servers = parse_command_line_stub_domain( stubDomain )
if domain is None:
print "stubDomain %s is in invalid format" % stubDomain
continue
stubDomains[ domain ] = dns_servers
if len( stubDomains ) > 0:
kube_dns = dump_kube_dns_cm( args.kube_dns_cm_file )
stubDomains.update( json.loads( kube_dns['data']['stubDomains'] ) if 'data' in kube_dns and 'stubDomains' in kube_dns['data'] else {} )
if 'data' not in kube_dns: kube_dns['data'] = {}
kube_dns['data']['stubDomains'] = json.dumps( stubDomains )
update_kube_dns( kube_dns, args.dry_run )
def del_stub_domains( args ):
"""
delete the stub domains
"""
kube_dns = dump_kube_dns_cm( args.kube_dns_cm_file )
# if no stubDomains, nothing to do
if 'data' not in kube_dns or 'stubDomains' not in kube_dns['data']:
return None
# remove the stubDomain by name
stubDomains = json.loads( kube_dns['data']['stubDomains'] )
deletedDomains = 0
for domain in args.stubDomains:
if domain in stubDomains:
del stubDomains[ domain ]
deletedDomains += 1
# if something is deleted, update the kube-dns
if deletedDomains > 0:
if len( stubDomains ) > 0:
kube_dns['data']['stubDomains'] = json.dumps( stubDomains )
else:
del kube_dns['data']['stubDomains']
update_kube_dns( kube_dns, args.dry_run )
def parse_args():
"""
parse the command line arguments
"""
parser = argparse.ArgumentParser( description = "nls DNS management tool" )
subparsers = parser.add_subparsers( help = "sub commands" )
dump_parser = subparsers.add_parser( "dump", help = "dump the kube-dns ConfigMap for debug purpose" )
dump_parser.set_defaults( func = dump_kube_dns )
list_upstream_parser = subparsers.add_parser( "list-upstream", help = "list all upstream dns servers" )
list_upstream_parser.set_defaults( func = list_upstreams )
add_upstream_parser = subparsers.add_parser( "add-upstream", help = "add upstream dns servers" )
add_upstream_parser.add_argument( "upstreamServers", nargs = "+", help = "the upstream DNS servers" )
add_upstream_parser.add_argument( "--kube-dns-cm-file", help = "the dumped kube-dns configuration file", required = False )
add_upstream_parser.add_argument( "--dry-run", action = "store_true", help = "dry run it" )
add_upstream_parser.set_defaults( func = add_upstreams )
del_upstream_parser = subparsers.add_parser( "del-upstream", help = "delete upstream dns servers" )
del_upstream_parser.add_argument( "upstreamServers", nargs = "+", help = "the upstream DNS servers" )
del_upstream_parser.add_argument( "--kube-dns-cm-file", help = "the dumped kube-dns configuration file", required = False )
del_upstream_parser.add_argument( "--dry-run", action = "store_true", help = "dry run it" )
del_upstream_parser.set_defaults( func = del_upstreams )
list_stub_domains_parser = subparsers.add_parser( "list-stub-domains", help = "list all stub-domains DNS servers" )
list_stub_domains_parser.add_argument( "--kube-dns-cm-file", help = "the dumped kube-dns configuration file", required = False )
list_stub_domains_parser.set_defaults( func = list_stub_domains )
add_stub_domains_parser = subparsers.add_parser( "add-stub-domains", help = "add stub-domains DNS servers" )
add_stub_domains_parser.add_argument( "--kube-dns-cm-file", help = "the dumped kube-dns configuration file", required = False )
add_stub_domains_parser.add_argument( "--dry-run", action = "store_true", help = "dry run it" )
add_stub_domains_parser.add_argument( "stubDomains", nargs = "+", help = "stub domain DNS server in format domain:dns-server-1,dns-server-2,...,dns-server-3" )
add_stub_domains_parser.set_defaults( func = add_stub_domains )
del_stub_domains_parser = subparsers.add_parser( "del-stub-domains", help = "delete stub-domains DNS servers" )
del_stub_domains_parser.add_argument( "--kube-dns-cm-file", help = "the dumped kube-dns configuration file", required = False )
del_stub_domains_parser.add_argument( "--dry-run", action = "store_true", help = "dry run it" )
del_stub_domains_parser.add_argument( "stubDomains", nargs = "+", help = "name of stub domain" )
del_stub_domains_parser.set_defaults( func = del_stub_domains )
return parser.parse_args()
def main():
args = parse_args()
args.func( args )
if __name__ == "__main__":
main()