Last active
May 27, 2024 14:42
-
-
Save sebpiq/02589f499c9920e70e924580a3fa9b9e to your computer and use it in GitHub Desktop.
envstore.py workaround for reusing the result of previous commands in a Dockerfile.
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
# In the following example usage of envstore.py, we want to get dynamically the home directory | |
# of a newly created user. | |
# We run the command to get that directory path once, and store the result using `envstore.py` | |
# with key `USER_HOME`. | |
FROM ubuntu:bionic | |
# Python 3.7 is needed for envstore.py | |
RUN apt-get update && apt-get install -qy software-properties-common | |
RUN add-apt-repository -y ppa:deadsnakes/ppa | |
RUN apt-get update && apt-get install -qy python3.7 | |
COPY envstore.py /usr/local/bin | |
# Running the tests | |
RUN envstore.py test | |
# Create a new user | |
ENV USER john | |
RUN adduser --disabled-password --gecos "" $USER | |
# Stores the new user home directory to variable USER_HOME | |
RUN envstore.py set USER_HOME $(getent passwd $USER | cut -f6 -d":") | |
# New User always gets greeted when starting bash session | |
RUN echo "echo 'greetings!!!'" >> $(envstore.py get USER_HOME)/.bashrc |
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/env python3.7 | |
import os | |
import sys | |
HOME = os.environ.get('HOME', '/root') | |
ENV_JSON_PATH = os.path.join(HOME, 'envstore.env') | |
def load_env_dict(): | |
if not os.path.exists(ENV_JSON_PATH): | |
return None | |
with open(ENV_JSON_PATH, 'r') as fd: | |
env_str = fd.read() | |
env_str = env_str.strip() | |
env_dict = {} | |
for pair in env_str.split('\n'): | |
if not pair: | |
continue | |
key, value = pair.split('=') | |
env_dict[key] = value | |
return env_dict | |
def write_env_dict(env_dict): | |
env_str = '\n'.join([ f'{k}={v}\n' for k, v in env_dict.items() ]) | |
with open(ENV_JSON_PATH, 'w') as fd: | |
fd.write(env_str) | |
def get_var(name): | |
env_dict = load_env_dict() or {} | |
return env_dict[name] | |
def set_var(name, value): | |
env_dict = load_env_dict() or {} | |
env_dict[name] = value | |
write_env_dict(env_dict) | |
def print_usage(exit_code=None): | |
print( | |
f'Minimalist environment variable store for usage with docker.\nUsage : \n' | |
f'\t{sys.argv[0]} get <key>\n' | |
f'\t{sys.argv[0]} set <key> <value>' | |
) | |
if exit_code is not None: | |
sys.exit(exit_code) | |
def main(args): | |
if len(args) < 1: | |
print_usage(1) | |
command = args.pop(0) | |
if command == 'get': | |
if len(args) != 1: | |
print_usage(1) | |
key = args.pop(0) | |
try: | |
print(get_var(key)) | |
except KeyError: | |
sys.stderr.write(f'Unknown key "{key}"\n') | |
elif command == 'set': | |
if len(args) != 2: | |
print_usage(1) | |
key = args.pop(0) | |
value = args.pop(0) | |
set_var(key, value) | |
elif command == 'test': | |
import unittest | |
global ENV_JSON_PATH | |
ENV_JSON_PATH = '/tmp/envstore.json' | |
class BaseTestCase(unittest.TestCase): | |
def setUp(self): | |
with open(ENV_JSON_PATH, 'w') as fd: | |
fd.write('bla=haha') | |
class TestGetSetUnit(BaseTestCase): | |
def test_get_var_existing(self): | |
self.assertEqual(get_var('bla'), 'haha') | |
def test_get_var_unknown(self): | |
with self.assertRaises(KeyError): | |
get_var('blo') | |
def test_get_var_file_unexisting(self): | |
os.remove(ENV_JSON_PATH) | |
with self.assertRaises(KeyError): | |
get_var('blo') | |
def test_set_var_existing(self): | |
set_var('bla', 'hoho') | |
self.assertEqual(get_var('bla'), 'hoho') | |
def test_set_var_new(self): | |
set_var('blo', 'hihi') | |
self.assertEqual(get_var('bla'), 'haha') | |
self.assertEqual(get_var('blo'), 'hihi') | |
class TestCommands(BaseTestCase): | |
def test_get_command(self): | |
main(['get', 'bla']) | |
def test_set_command(self): | |
main(['set', 'bla', 'hoho']) | |
self.assertEqual(get_var('bla'), 'hoho') | |
unittest.TextTestRunner(verbosity=2).run(unittest.TestSuite([ | |
unittest.TestLoader().loadTestsFromTestCase(TestGetSetUnit), | |
unittest.TestLoader().loadTestsFromTestCase(TestCommands) | |
])) | |
else: | |
print(f'ERROR: unrecognized command {command}') | |
print_usage(1) | |
if __name__ == '__main__': | |
args = sys.argv[1:] | |
main(args) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment