Last active
December 22, 2015 11:38
-
-
Save smoser/6466708 to your computer and use it in GitHub Desktop.
parse_shell_config: basically reads a "shell config" in python by running it with bash, and then reading the variables declared.
It returns an dict with the variables found after running that code.
the point of using this is that some software has "config" in shell format (ie, 'openrc' in openstack).
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
DISK_ID='1' | |
ETH0_DNS='10.0.0.1' | |
ETH0_GATEWAY='10.0.0.1' | |
ETH0_IP='10.0.0.72' | |
ETH0_MASK='255.255.255.0' | |
FILES_DS='/var/lib/one/datastores/2/9c92ad910c0b30a411ccdfc141bc7a25:'\''jfopet.sh'\'' ' | |
FILES_URL='http://10.0.0.11/files/installer.tar.gz' | |
INIT_SCRIPTS='jfopet.sh' | |
MANIFEST='ubuntu-kvm1' | |
SSH_PUBLIC_KEY='ssh-dss AAAAB3NzaC1kc3MAAACBANprdUVFRaADZXZaAm2elpRaUGCMETLLuYYJCDUZPb0Dh/V7KeM2/a3rFIDA0s5sVK2XQNqLHyy0U8xA/0R8dplmg7BDckkAzhrDVpEGnQE1fk/xPd1t7u+yeVqpbrfyAmfmyE2P980mhBoWalbeV/f7SmHUP8RiQ2hlAWUxr7I5AAAAFQDLHhFndbcA7svGd/yfY6nU4ubodwAAAIAoXLKlckmZur1pc9TN4XoHa+Fl/6Qpu0XO7Ai/tu8dqHlN+FpVk8BQNnokwE+EZBARLIL0JCjHpT9b5aEvlpRz3TuDa6az8wvJRlScNufmVrf0ls1WCFDHujSLzd3aOkKct35Aamf1amP/NPE2aGne/tPS7HQ3TCf5E2MAQzYVJKSARwAAAIAaVqvU7LfGMEw0hEXr7fuJCMHh4FmPvejiOoSUz2GOU5bceasRitdulCQJbNiVtY6U0S+qQ0X8rvAnG934p4zS9TtgKIhplr146fkbYnNjCaAM0rNVvTh2SzEEKJiG2G1d3wyNuO8wpPhIiJ1OVZrGwkVyWwiNzC2sWXAXldQ9Hg== user1@host | |
ssh-dss AAAAB3NzaC1kc3MAAACBANBWTQmm4GtkAiPpA20DK1TQd1n7UoC5BymTHlGzFmj+BsQdn6ZZbihV/roNVo1roJhb2hQq/WuQR50D72vMIjrC6t1DkofFBL0iz+mb7JdmNxbE7cnOHMxEr/cd4ds4EwzpBKiQzt8NNcz/zbSadHQtBd0+u1G5nvm4MXHNVYQnAAAAFQDbEN554Or4vd7D+2wzjs3c1nNOowAAAIAdRlTrRG1YmceKHh3urcltniIoo8FrNudwCShbHTCOQbM+KkMUTtw5qwWFuJP6HdaLjmUehqxqDWeWGp8c2y5yMee0JR5cx+iMwhg1Q2o4S6c+zgWdUYIVkuPgYOOR2GMCPdl9mwcxtVvpHD59UFlPh16oLzakUCSxkro5V/LUXxuywAAAIBtYvxfwI5Cl0xq3/KQI7giNef05EXIgK+KwYu3xC6fs+7NxQYFzMsSEQhEJI62J091Kh0RFpFPdGPECIQolt8j4ltymKM9+pfgiE7oBXSxkW44XadBnCWCGU5B4gTnz84VKECWuu2J9Z4cn44hKYt1uj0SxxzExnB1X51kUN+Z5Q== user2@host' |
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
#!/bin/bash | |
NOVARC_CONFIG_VERSION=1 | |
# allow python-keyring usage, as configured in | |
# HOME/.local/share/python_keyring/keyringrc.cfg | |
export OS_NO_CACHE=${OS_NO_CACHE:-0} | |
NOVARC=$(readlink -f "${BASH_SOURCE:-${0}}" 2>/dev/null) || | |
NOVARC=$(python -c 'import os,sys; print os.path.abspath(os.path.realpath(sys.argv[1]))' "${BASH_SOURCE:-${0}}") | |
NOVA_KEY_DIR=${NOVARC%/*} | |
export OS_USERNAME="smoser" | |
export OS_TENANT_NAME="smoser_project" | |
export OS_PASSWORD="ABCDEFGHIJKL" | |
export OS_AUTH_URL="https://keystone.openstack.example.com:443/v2.0/" | |
export OS_REGION_NAME="${OS_REGION_NAME:-dtw01}" | |
export NOVA_USERNAME="${OS_USERNAME}" | |
export NOVA_PASSWORD="${OS_PASSWORD}" | |
export NOVA_PROJECT_ID="${OS_TENANT_NAME}" | |
export NOVA_VERSION="1.1" | |
export NOVA_REGION="${OS_REGION_NAME}" | |
export EC2_ACCESS_KEY="abcdef0123456789abcdef0123456789" | |
export EC2_SECRET_KEY="0123456789abcdef0123456789abcdef" | |
export EC2_URL="https://ec2-${OS_REGION_NAME}.openstack.example.com:443/services/Cloud" | |
export S3_URL="http://s3-${OS_REGION_NAME}.openstack.example.com:3333" | |
export EC2_USER_ID=42 # nova does not use user id, but bundling requires it | |
export EC2_PRIVATE_KEY=${NOVA_KEY_DIR}/pk.pem | |
export EC2_CERT=${NOVA_KEY_DIR}/cert.pem | |
export NOVA_CERT=${NOVA_KEY_DIR}/cacert.pem | |
export EUCALYPTUS_CERT=${NOVA_CERT} # euca-bundle-image seems to require this set | |
alias ec2-bundle-image="ec2-bundle-image --cert ${EC2_CERT} --privatekey ${EC2_PRIVATE_KEY} --user 42 --ec2cert ${NOVA_CERT}" | |
alias ec2-upload-bundle="ec2-upload-bundle -a ${EC2_ACCESS_KEY} -s ${EC2_SECRET_KEY} --url ${S3_URL} --ec2cert ${NOVA_CERT}" | |
export NOVA_API_KEY="${EC2_ACCESS_KEY}" |
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/python | |
import subprocess | |
import string | |
def parse_shell_config(content=None, filepath=None, keylist=None, bash=None, | |
asuser=None): | |
if content is None and filepath is None: | |
raise ValueError("content and filepath cannot be None") | |
elif content is not None and filepath is not None: | |
raise ValueError("content and filepath cannot both be set") | |
if isinstance(bash, str): | |
bash = [bash] | |
elif bash is None: | |
bash = ['bash', '-e'] | |
if filepath is not None: | |
content = ". '%s'" % filepath | |
# allvars expands to all existing variables by using '${!x*}' notation | |
# where x is lower or upper case letters or '_' | |
allvars = ["${!%s*}" % x for x in string.letters + "_"] | |
keylist_in = keylist | |
if keylist is None: | |
keylist = allvars | |
keylist_in = [] | |
setup = '\n'.join(('__v="";', '',)) | |
def varprinter(vlist): | |
# output '\0'.join(['_start_', key=value NULL for vars in vlist] | |
return '\n'.join(( | |
'printf "%s\\0" _start_', | |
'for __v in %s; do' % ' '.join(vlist), | |
' printf "%s=%s\\0" "$__v" "${!__v}";', | |
'done', | |
'' | |
)) | |
# the rendered 'bcmd' is bash syntax that does | |
# setup: declare variables we use (so they show up in 'all') | |
# varprinter(allvars): print all variables known at beginning | |
# content: execute the provided content | |
# varprinter(keylist): print all variables known after content | |
# | |
# output is then a null terminated array of: | |
# literal '_start_' | |
# key=value (for each preset variable) | |
# literal '_start_' | |
# key=value (for each post set variable) | |
bcmd = ('unset IFS\n' + | |
setup + | |
varprinter(allvars) + | |
'{\n%s\n\n} > /dev/null\n' % content + | |
'unset IFS\n' + | |
varprinter(keylist) + "\n") | |
cmd = [] | |
if asuser is not None: | |
cmd = ['sudo', '-u', asuser] | |
cmd.extend(bash) | |
sp = subprocess.Popen(cmd, stdin=subprocess.PIPE, | |
stdout=subprocess.PIPE) | |
(output, error) = sp.communicate(input=bcmd) | |
if sp.returncode != 0: | |
raise Exception("Process returned %d" % sp.returncode) | |
# exclude vars in bash that change on their own or that we used | |
excluded = ("RANDOM", "LINENO", "_", "__v") | |
preset = {} | |
ret = {} | |
target = None | |
output = output[0:-1] # remove trailing null | |
# go through output. First _start_ is for 'preset', second for 'target'. | |
# Add to target only things were changed and not in volitile | |
for line in output.split("\0"): | |
try: | |
(key, val) = line.split("=", 1) | |
if target is preset: | |
target[key] = val | |
elif (key not in excluded and | |
(key in keylist_in or preset.get(key) != val)): | |
ret[key] = val | |
except ValueError: | |
if line != "_start_": | |
raise | |
if target is None: | |
target = preset | |
elif target is preset: | |
target = ret | |
return ret | |
if __name__ == '__main__': | |
import pprint | |
import sys | |
with open(sys.argv[1], "r") as fp: | |
content = fp.read() | |
asuser = None | |
if len(sys.argv) > 2: | |
asuser = sys.argv[2] | |
#pprint.pprint(parse_shell_config(filepath=sys.argv[1], asuser=asuser)) | |
pprint.pprint(parse_shell_config(content=content, asuser=asuser)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
U da bomb!