Parser: update for loop syntax

This commit is contained in:
Akemi Izuko 2024-07-17 19:24:52 -06:00
parent 63ff7d5338
commit c291a3f5cb
Signed by: akemi
GPG key ID: 8DE0764E1809E9FC

View file

@ -42,37 +42,32 @@ def run_assertions(host, props):
# │ Pαrsεr | # │ Pαrsεr |
# ╚───────────────────────────────────────────────────────────────────────────╝ # ╚───────────────────────────────────────────────────────────────────────────╝
def expand_for_loop(props): def expand_for_loop(props):
expand = list() expanded_props = dict()
for loop in props.get("for", []): for loop in props.get("for", []):
r = loop["range"] prop = loop["property"]
if isinstance(r, dict): if expanded_props.get(prop) is None:
start = int(r["from"]) expanded_props[prop] = list()
cease = int(r["to"])
inc = int(r.get("increment", 1))
iterations = range(start, cease, inc) if loop.get("range"):
elif isinstance(r, list): r = loop["range"]
iterations = r start = int(r[0])
cease = int(r[1])
incre = int(r[2]) if len(r) > 2 else 1
iterations = range(start, cease, incre)
elif loop.get("iter"):
iterations = loop["iter"]
else: else:
raise TypeError("Expected list or dict in `for` loop `range`") raise TypeError("Expected a `range` or `iter` property on `for`")
pattern = re.compile(rf'\$\{{{loop["variable"]}\}}') pattern = re.compile(rf'\$\{{{loop["variable"]}\}}')
for i in iterations: for i in iterations:
expand.append(pattern.sub(str(i), loop["template"])) expanded_props[prop].append(pattern.sub(str(i), loop["template"]))
return expand return expanded_props
def get_ssh_props(data):
props = dict()
for k, v in data["ssh_props"].items():
props[k] = v if isinstance(v, list) else [v]
return props
def parse_props(host, props, hosts): def parse_props(host, props, hosts):
@ -83,25 +78,11 @@ def parse_props(host, props, hosts):
parsed[k] = v if isinstance(v, list) else [v] parsed[k] = v if isinstance(v, list) else [v]
# For-loops in config # For-loops in config
for loop in props.get("for", []): for prop, values in expand_for_loop(props).items():
prop = loop["property"] if parsed.get(prop) is not None:
r = loop["range"] parsed[prop].extend(values)
if isinstance(r, dict):
iterations = range(r["from"], r["to"])
elif isinstance(r, list):
iterations = r
else: else:
raise TypeError("Expected list or dict in `for` loop `range`") parsed[prop] = values
if not parsed.get(prop):
parsed[prop] = list()
pattern = re.compile(rf'\$\{{{loop["variable"]}\}}')
for i in iterations:
sub = pattern.sub(str(i), loop["template"])
parsed[prop].append(sub)
# Inherit from template # Inherit from template
template = props.get("template") template = props.get("template")
@ -128,22 +109,6 @@ def remove_templates(expanded):
return hosts return hosts
def stringify_booleans(props):
pattern = re.compile(r"(True|False)$")
def replace_bools(s):
m = pattern.search(s)
if m and m[1] == "True":
return pattern.sub("true", s)
elif m and m[1] == "False":
return pattern.sub("false", s)
else:
return s
return [replace_bools(prop) for prop in props]
def parse_yaml(data): def parse_yaml(data):
hosts = dict() hosts = dict()
check_duplicate_hosts(data) check_duplicate_hosts(data)
@ -180,15 +145,16 @@ def to_ssh_config_string(parse):
# ╔───────────────────────────────────────────────────────────────────────────╗ # ╔───────────────────────────────────────────────────────────────────────────╗
# │ Mαiη | # │ Mαiη |
# ╚───────────────────────────────────────────────────────────────────────────╝ # ╚───────────────────────────────────────────────────────────────────────────╝
with open(args.file, "r") as f: if __name__ == '__main__':
data = yaml.safe_load(f) with open(args.file, "r") as f:
data = yaml.safe_load(f)
parse = parse_yaml(data) parse = parse_yaml(data)
if args.json: if args.json:
print(json.dumps(parse)) print(json.dumps(parse))
elif args.out: elif args.out:
with open(args.out, "w") as f: with open(args.out, "w") as f:
f.write(to_ssh_config_string(parse)) f.write(to_ssh_config_string(parse))
else: else:
print(to_ssh_config_string(parse), end="") print(to_ssh_config_string(parse), end="")