Compare commits

...

2 commits

Author SHA1 Message Date
Akemi Izuko 7293796883
Parser: fix config parser 2024-05-26 22:17:06 -06:00
Akemi Izuko fe2d1cfa14
Parser: config to yaml parser 2024-05-26 22:09:00 -06:00
2 changed files with 79 additions and 4 deletions

View file

@ -37,12 +37,29 @@ coronation:
Hostname: coronation.cs.ualberta.ca
```
## Rules
## Quick Start
```bash
mv ~/.ssh/config ~/.ssh/config_og
python3 src/ssh_config_to_yaml.py ~/.ssh/config_og --out ~/.ssh/config.yaml
# Do some edits on ~/.ssh/config.yaml. The migration script won't compress
# things with for-loops or templates. Then...
python3 ~/.ssh/config.yaml --out ~/.ssh/config
```
As a proof of concept, you can even chain the scripts! The order of hosts will
change, but the config should function identically!
```bash
python3 src/main.py <(python3 src/ssh_config_to_yaml.py ~/.ssh/config)
```
# Rules
The `src/ssh_config_to_yaml.py` script will assist in quickly migrating your
existing config.
#### SSH Properties
### SSH Properties
Standard SSH config properties go under the `ssh_props` heading for every host.
For example:
@ -72,7 +89,7 @@ github.com:
Note that yaml does not support duplicate keys, so keys can take a list of
properties instead to mimic repeated keys, as seen above.
#### Templates
### Templates
Templates are "default" properties inherited from another host. Templates must
be declared above the host that uses it. You can make a template-only host by
@ -153,7 +170,7 @@ Host ohaton
LocalForward 9000 localhost:9000
```
#### For loops
### For loops
For loops allow simple substitution of a single variable over a range or set of
values. Ranges must be numerical, but sets can be any arbitrary string. Multiple

58
src/ssh_config_to_yaml.py Normal file
View file

@ -0,0 +1,58 @@
import argparse
import json
import re
import yaml
from pathlib import Path
parser = argparse.ArgumentParser(description="Process some integers.")
parser.add_argument("file", type=Path, help="yaml config")
parser.add_argument("--json", action="store_true", help="output parse as json")
parser.add_argument("--out", type=Path, help="write into file")
args = parser.parse_args()
def parse_sshconfig(lines):
parse = dict()
hostname = None
host = dict()
re_host = re.compile(r"^\s*Host (.+)$")
re_prop = re.compile(r"^\s*([A-Za-z]+)[ =](.+)$")
for line in lines:
m_host = re_host.match(line)
m_prop = re_prop.match(line)
if m_host:
if hostname is not None:
parse[hostname] = { "ssh_props": host }
hostname = m_host[1]
host = dict()
elif m_prop and host.get(m_prop[1]):
host[m_prop[1]].append(m_prop[2])
elif m_prop:
host[m_prop[1]] = [m_prop[2]]
if hostname is not None:
parse[hostname] = { "ssh_props": host }
return parse
# ╔───────────────────────────────────────────────────────────────────────────╗
# │ Mαiη |
# ╚───────────────────────────────────────────────────────────────────────────╝
with open(args.file, "r") as f:
lines = f.read().splitlines()
parse = parse_sshconfig(lines)
if args.json:
print(json.dumps(parse))
elif args.out:
with open(args.out, "w") as f:
f.write(yaml.dump(parse))
else:
print(yaml.dump(parse), end="")