I just started learning Python. I try to create a data structure from the file wg.conf
I'm stuck on creating an array Peers. I need to create multiple Peer entries inside that array.
Config file example:
[Interface]
Address = 10.200.200.1/24
ListenPort = 10086
PrivateKey = [Server's private key]
[Peer]
# Client 1
PublicKey = [Client's public key]
AllowedIPs = 10.200.200.2/32
[Peer]
# Client 2
PublicKey = [Client's public key]
AllowedIPs = 10.200.200.2/32
I want to get this result
{
"srv_addr": "10.10.10.1",
"srv_port": 123456,
"pub_key": "Asdfghh",
"prv_key": "Asdfghh",
"peers": [
{
"comment": "Some Dev",
"addr": "10.10.10.2",
"pub_key": "SAssadfafa"
},
{
"comment": "Some Dev2",
"addr": "10.10.10.3",
"pub_key": "SAssadfafa"
}
]
}
My code is
import json
wg_conf = "/etc/wireguard/wg0.conf"
iface = ""
result = {}
result["peers"] = {}
i = 0
with open(wg_conf) as file:
while line := file.readline():
if line.startswith("[Interface]"):
iface = "srv"
elif line.startswith("[Peer]"):
iface = "peer"
if iface == "srv":
if line.startswith("Address"):
result["srv_addr"] = line.split()[2]
if line.startswith("ListenPort"):
result["srv_port"] = line.split()[2]
if line.startswith("PrivateKey"):
result["srv_priv_key"] = line.split()[2]
elif iface == "peer":
if line.startswith('#'):
result["peers"]["comment"] = (line.replace('#', "").replace("\n", "")
if line.startswith("PublicKey"):
result["peers"]["pub_key"] = line.split()[2]
i+= 1
if line.startswith("AllowedIPs"):
result["peers"]["allow_ip"] = line.split()[2]
print (result)
Output is:
{'peers': {'comment': 'Som Dev', 'pub_key': 'SKSKSKS', 'allow_ip': '10.10.10.2/32'}***, 'srv_addr': '10.10.10.1/24', 'srv_port': '12345', 'srv_priv_key': 'wrehwrhrwh'}
I need:
{'peers': [{'comment': 'Som Dev', 'pub_key': 'SKSKSKS', 'allow_ip': '10.10.10.2/32'},{'comment': 'Som Dev2', 'pub_key': 'hrhrhw', 'allow_ip': '10.10.10.3/32'}], 'srv_addr': '10.10.10.1/24', 'srv_port': '12345', 'srv_priv_key': 'wrehwrhrwh'}
# ^ ^
I assume you are parsing a file like this one.
There are three problems.
You are incrementing the index i
, but then you are not using this index to reference the elements of the nested array.
If the structure you wish to build for result["peers"] is something like:
result["peers"][0] = { "peer_comment": "Some Dev", "peer_allow_ip": "10.10.10.2", "peer_pub_key": "SAssadfafa" }
result["peers"][1] = { "peer_comment": "Some other Dev", "peer_allow_ip": "10.10.10.3", "peer_pub_key": "SAssasdfdsf" }
Then you just need to insert the index in the middle:
if line.startswith('#'):
result["peers"][i]["peer_comment"] = (line.replace('#', "").replace
if line.startswith("PublicKey"):
result["peers"][i]["peer_pub_key"] = line.split()[2]
if line.startswith("AllowedIPs"):
result["peers"][i]["peer_allow_ip"] = line.split()[2]
You are incrementing the index in the wrong place. Assuming your config file is in this exact order, by the time you reach to the PublicKey
parameter, you are already updating the data for the next peer.
Consider this slight change:
i = -1
with open(wg_conf) as file:
while line := file.readline():
if line.startswith("[Interface]"):
iface = "srv"
elif line.startswith("[Peer]"):
iface = "peer"
i += 1 # It becomes 0 as soon as we hit the first [Peer] block
Meaning that as soon as a [Peer]
section is encountered, the index will be increased for all the items within that section.
results["peers"]
is initialised a dictionary not a list, so you should change the line to:
results["peers"] = []
Then, it will be beneficial to also prepare the nested dictionary right after the incremental discussed above, that is:
i += 1
results["peers"].append({})
i
Since now you are kind of "synchronising" the value with i
with the .append()
command, perhaps you can do something a little simpler than that, and just refer to the "last created element", which is expressed as [-1]
. As long as the structure of the file is consistent, this would work.
Here how the code overall would look like:
#import json - Not needed in this code
wg_conf = "/etc/wireguard/wg0.conf"
iface = ""
result = {}
result["peers"] = []
with open(wg_conf) as file:
while line := file.readline():
if line.startswith("[Interface]"):
iface = "srv"
elif line.startswith("[Peer]"):
iface = "peer"
result["peers"].append({})
if iface == "srv":
if line.startswith("Address"):
result["srv_addr"] = line.split()[2]
if line.startswith("ListenPort"):
result["srv_port"] = line.split()[2]
if line.startswith("PrivateKey"):
result["srv_priv_key"] = line.split()[2]
elif iface == "peer":
if line.startswith('#'):
result["peers"][-1]["comment"] = line.replace('#', "").replace("\n", "") # Fixed a typo here
if line.startswith("PublicKey"):
result["peers"][-1]["pub_key"] = line.split()[2]
if line.startswith("AllowedIPs"):
result["peers"][-1]["allow_ip"] = line.split()[2]
print (result)
This is the output when I ran the script with your example .conf file:
{
'peers':
[
{
'comment': ' Client 1',
'pub_key': "[Client's",
'allow_ip': '10.200.200.2/32'
},
{
'comment': ' Client 2',
'pub_key': "[Client's",
'allow_ip': '10.200.200.2/32'
}
],
'srv_addr': '10.200.200.1/24',
'srv_port': '10086',
'srv_priv_key': "[Server's"
}