forked from envoyproxy/envoy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
socket_passing.py
executable file
·127 lines (114 loc) · 5.19 KB
/
socket_passing.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
#!/usr/bin/env python3
# This tool is a helper script that queries the admin address for all listener
# addresses after envoy startup. (The admin address is written out to a file by
# setting the -a flag in the envoy binary.) The script then outputs a new json
# config file with updated listener addresses. This script is currently called
# in the hot restart integration test to update listener addresses bound to
# port 0 in the initial json config file.
import argparse
import http.client
import json
import os.path
import re
import sys
import time
# Seconds to wait for the admin address output file to appear. The script exits
# with failure if the file is not found.
ADMIN_FILE_TIMEOUT_SECS = 20
# Because the hot restart files are yaml but yaml support is not included in
# python by default, we parse this fairly manually.
def generate_new_config(original_yaml, admin_address, updated_json):
# Get original listener addresses
with open(original_yaml, 'r') as original_file:
sys.stdout.write('Admin address is ' + admin_address + '\n')
try:
admin_conn = http.client.HTTPConnection(admin_address)
admin_conn.request('GET', '/listeners?format=json')
admin_response = admin_conn.getresponse()
if not admin_response.status == 200:
return False
discovered_listeners = json.loads(admin_response.read().decode('utf-8'))
except Exception as e:
sys.stderr.write('Cannot connect to admin: %s\n' % e)
return False
else:
raw_yaml = original_file.readlines()
index = 0
for discovered in discovered_listeners['listener_statuses']:
replaced = False
addresses = (
discovered['additional_local_addresses'] + [discovered['local_address']] if
discovered.get('additional_local_addresses') else [discovered['local_address']])
for local_address in addresses:
if 'pipe' in local_address:
path = local_address['pipe']['path']
for index in range(index + 1, len(raw_yaml) - 1):
if 'pipe:' in raw_yaml[index] and 'path:' in raw_yaml[index + 1]:
raw_yaml[index + 1] = re.sub(
'path:.*', 'path: "' + path + '"', raw_yaml[index + 1])
replaced = True
break
else:
addr = local_address['socket_address']['address']
port = str(local_address['socket_address']['port_value'])
if addr[0] == '[':
addr = addr[1:-1] # strip [] from ipv6 address.
for index in range(index + 1, len(raw_yaml) - 2):
if ('socket_address:' in raw_yaml[index]
and 'address:' in raw_yaml[index + 1]
and 'port_value:' in raw_yaml[index + 2]):
raw_yaml[index + 1] = re.sub(
'address:.*', 'address: "' + addr + '"', raw_yaml[index + 1])
raw_yaml[index + 2] = re.sub(
'port_value:.*', 'port_value: ' + port, raw_yaml[index + 2])
replaced = True
break
if replaced:
sys.stderr.write(
'replaced listener at line ' + str(index) + ' with ' + str(discovered)
+ '\n')
else:
sys.stderr.write(
'Failed to replace a discovered listener ' + str(discovered) + '\n')
return False
with open(updated_json, 'w') as outfile:
outfile.writelines(raw_yaml)
finally:
admin_conn.close()
return True
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Replace listener addressses in json file.')
parser.add_argument(
'-o',
'--original_json',
type=str,
required=True,
help='Path of the original config json file')
parser.add_argument(
'-a',
'--admin_address_path',
type=str,
required=True,
help='Path of the admin address file')
parser.add_argument(
'-u',
'--updated_json',
type=str,
required=True,
help='Path to output updated json config file')
args = parser.parse_args()
admin_address_path = args.admin_address_path
# Read admin address from file
counter = 0
while not os.path.exists(admin_address_path):
time.sleep(1)
counter += 1
if counter > ADMIN_FILE_TIMEOUT_SECS:
break
if not os.path.exists(admin_address_path):
sys.exit(1)
with open(admin_address_path, 'r') as admin_address_file:
admin_address = admin_address_file.read()
success = generate_new_config(args.original_json, admin_address, args.updated_json)
if not success:
sys.exit(1)