Last active
May 1, 2020 20:04
-
-
Save usbpc/0d3c1254cd4e76d569d1ecafac34b2cb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
network: | |
version: 2 | |
renderer: networkd | |
ethernets: | |
enp3s0: | |
addresses: | |
- @@IP_SUBNET@@ | |
gateway4: @@GATEWAY@@ | |
nameservers: | |
addresses: [@@DNS@@] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This is a very simpelistic example file | |
bind_addr=@@SERVER_ADDR@@ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
# This script is intended to allow easier rollout of software to multiple servers | |
# that each have a slightly diffrent configuration. There also need to be | |
# template configuration files provided, that have placeholders in the places | |
# where the values need to be inserted. The placeholder will need to have the form | |
# @@PLACEHOLDER_NAME@@. | |
# To work it first asks the user for input, then does some light processing on the | |
# user inputs. After that it copies files while replacing the placeholders. At the | |
# end it executes some shell commands. | |
# This is the place where the values the user will be asked for are defined. | |
# name => internal name for the placeholder | |
# prompt => the text displayed to the user when asked for this placeholder value | |
# regex => regex used for validation of user input | |
# repeated (optional) => indicates, that the user can input multiple values | |
# break (required if repeated) => regex for what needs to be input during 'repeated' | |
# values to get to the next prompt | |
# start (optional, only used if repeated) => string to prepend before any | |
# repeated values are put into string form | |
# seperator (optional, only used if repeated) => string to insert between | |
# repeated values for string form | |
# end (optional, only used if repeated) => string to append after all | |
# repeated values are put into string form | |
placeholders = [ | |
{ | |
'name':'IP_SUBNET', | |
'prompt':'IPv4 in CIDR notation: ', | |
'regex':r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2}', | |
}, | |
{ | |
'name':'GATEWAY', | |
'prompt':'IPv4 of the Default Gateway: ', | |
'regex':r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}' | |
}, | |
{ | |
'name':'DNS', | |
'prompt':'IPv4 of the DNS Servers, use the empty string to terminate: ', | |
'regex':r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', | |
'repeated': True, | |
'seperator':',', | |
'break':r'' | |
} | |
] | |
# This is where some light processing for placeholders is defined. It takes a 'src' | |
# placeholder and writes whatevery is in the first capture group of the 'regex' to | |
# write into the 'dst' placeholder. | |
pholders_processing = [ | |
{ | |
'src':'IP_SUBNET', | |
'dst':'IP', | |
'regex':r'(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\/\d{1,2}' | |
} | |
] | |
# Here the source and destination for files to be copied is defined. | |
# You also need to define what placeholders to use in a simple list of strings. | |
# Additionally to strings tuple pairs can be put in, an example is: | |
# ('IP', 'SERVER_ADDR') that can be read as 'use the IP placeholder, but for this | |
# file name it SERVER_ADDR'. | |
files = [ | |
{ | |
'src':'50-static-ip.yaml_template', | |
#Normally the destination for this would be set to /etc/netplan/50-static-ip.yaml | |
'dst':'50-static-ip.yaml', | |
'placeholders': ['IP_SUBNET', 'GATEWAY', 'DNS'] | |
}, | |
{ | |
'src':'example.conf_template', | |
'dst':'example.conf', | |
'placeholders': [('IP', 'SERVER_ADDR')] | |
} | |
] | |
# This defines a list of commands to be ran after everything else was processed. | |
# The commands will be executed in the order defined here. | |
post_commands = [ | |
['echo', 'Executed the command!'] | |
] | |
import re | |
import subprocess | |
replacments = dict() | |
for p in placeholders: | |
r = re.compile(p['regex']) | |
repeated = p.get('repeated') and p.get('break') is not None | |
if repeated: | |
b = re.compile(p['break']) | |
l = list() | |
while True: | |
prompt = p['prompt'] | |
tmp = input(f'{p.get("prompt")} ') | |
if r.fullmatch(tmp): | |
if repeated: | |
l.append(tmp) | |
else: | |
replacments[p['name']] = tmp | |
break | |
if repeated and b.fullmatch(tmp): | |
if p.get('start') is None: | |
p['start'] = '' | |
if p.get('seperator') is None: | |
p['seperator'] = '' | |
if p.get('end') is None: | |
p['end'] = '' | |
tmp = p['start'] | |
first = True | |
for x in l: | |
if not first: | |
tmp += p['seperator'] | |
first = False | |
tmp += x | |
tmp += p['end'] | |
replacments[p['name']] = tmp | |
break | |
for p in pholders_processing: | |
if replacments.get(p.get('src')) is not list: | |
r = re.compile(p['regex']) | |
m = r.fullmatch(replacments.get(p.get('src'))) | |
if m: | |
replacments[p.get('dst')] = m.groups()[0] | |
for file in files: | |
cur_placeholders = dict() | |
for x in file.get('placeholders'): | |
if type(x) is str: | |
cur_placeholders[x] = replacments.get(x) | |
elif type(x) is tuple: | |
cur_placeholders[x[1]] = replacments.get(x[0]) | |
with open(file.get('src'), 'rt') as fi: | |
with open(file.get('dst'), 'wt') as fo: | |
tmp = fi.read() | |
for p, r in cur_placeholders.items(): | |
tmp = tmp.replace(f'@@{p}@@', r) | |
fo.write(tmp) | |
print(f"moved '{file.get('src')} to '{file.get('dst')}'") | |
for cmd in post_commands: | |
r = subprocess.run(cmd, stdout=subprocess.PIPE) | |
print(r.stdout.decode('utf-8')) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment