Commit 40ff45e2 authored by Łukasz Nowak's avatar Łukasz Nowak

Allow to pass external environment during software build.

WIP. Idea needs some clarificatoin.
parent aaf2e015
...@@ -47,7 +47,7 @@ class Software(object): ...@@ -47,7 +47,7 @@ class Software(object):
"""This class is responsible of installing a software release""" """This class is responsible of installing a software release"""
def __init__(self, url, software_root, console, buildout, def __init__(self, url, software_root, console, buildout,
signature_private_key_file=None, upload_cache_url=None, signature_private_key_file=None, upload_cache_url=None,
upload_dir_url=None): upload_dir_url=None, software_environment=None):
"""Initialisation of class parameters """Initialisation of class parameters
""" """
self.url = url self.url = url
...@@ -60,6 +60,7 @@ class Software(object): ...@@ -60,6 +60,7 @@ class Software(object):
self.signature_private_key_file = signature_private_key_file self.signature_private_key_file = signature_private_key_file
self.upload_cache_url = upload_cache_url self.upload_cache_url = upload_cache_url
self.upload_dir_url = upload_dir_url self.upload_dir_url = upload_dir_url
self.software_environment = software_environment
def install(self): def install(self):
""" Fetches buildout configuration from the server, run buildout with """ Fetches buildout configuration from the server, run buildout with
...@@ -98,11 +99,12 @@ class Software(object): ...@@ -98,11 +99,12 @@ class Software(object):
buildout_parameter_list.extend(['-c', self.url]) buildout_parameter_list.extend(['-c', self.url])
utils.bootstrapBuildout(self.software_path, self.buildout, utils.bootstrapBuildout(self.software_path, self.buildout,
additional_buildout_parametr_list=buildout_parameter_list, additional_buildout_parametr_list=buildout_parameter_list,
console=self.console) console=self.console, environment=self.software_environment)
utils.launchBuildout(self.software_path, utils.launchBuildout(self.software_path,
os.path.join(self.software_path, 'bin', 'buildout'), os.path.join(self.software_path, 'bin', 'buildout'),
additional_buildout_parametr_list=buildout_parameter_list, additional_buildout_parametr_list=buildout_parameter_list,
console=self.console) console=self.console,
environment=self.software_environment)
finally: finally:
shutil.rmtree(extends_cache) shutil.rmtree(extends_cache)
......
...@@ -110,6 +110,8 @@ def parseArgumentTupleAndReturnSlapgridObject(*argument_tuple): ...@@ -110,6 +110,8 @@ def parseArgumentTupleAndReturnSlapgridObject(*argument_tuple):
parser.add_argument("--promise-timeout", parser.add_argument("--promise-timeout",
type=int, default=3, type=int, default=3,
help="Promise timeout in seconds.") help="Promise timeout in seconds.")
parser.add_argument("--software-environment-file", type=argparse.FileType(),
help="File containing environment overrides for software runs.")
parser.add_argument("configuration_file", nargs=1, type=argparse.FileType(), parser.add_argument("configuration_file", nargs=1, type=argparse.FileType(),
help="SlapOS configuration file.") help="SlapOS configuration file.")
...@@ -178,12 +180,20 @@ def parseArgumentTupleAndReturnSlapgridObject(*argument_tuple): ...@@ -178,12 +180,20 @@ def parseArgumentTupleAndReturnSlapgridObject(*argument_tuple):
# slapgrid scripts without this parameter. # slapgrid scripts without this parameter.
if signature_private_key_file: if signature_private_key_file:
mandatory_file_list.append(signature_private_key_file) mandatory_file_list.append(signature_private_key_file)
for f in mandatory_file_list: for f in mandatory_file_list:
if f is not None: if f is not None:
if not os.path.exists(f): if not os.path.exists(f):
parser.error('File %r does not exists.' % f) parser.error('File %r does not exists.' % f)
# process software environment overrides
software_environment = None
software_environment_file = option_dict.get('software_environment_file')
if software_environment_file is not None:
software_env_config = ConfigParser.SafeConfigParser()
software_env_config.optionxform = str
software_env_config.readfp(software_environment_file)
software_environment = dict(software_env_config.items('environment'))
certificate_repository_path = option_dict.get('certificate_repository_path') certificate_repository_path = option_dict.get('certificate_repository_path')
if certificate_repository_path is not None: if certificate_repository_path is not None:
if not os.path.isdir(certificate_repository_path): if not os.path.isdir(certificate_repository_path):
...@@ -216,7 +226,8 @@ def parseArgumentTupleAndReturnSlapgridObject(*argument_tuple): ...@@ -216,7 +226,8 @@ def parseArgumentTupleAndReturnSlapgridObject(*argument_tuple):
upload_dir_url=option_dict.get('upload-dir-url', None), upload_dir_url=option_dict.get('upload-dir-url', None),
console=option_dict['console'], console=option_dict['console'],
buildout=option_dict.get('buildout'), buildout=option_dict.get('buildout'),
promise_timeout=option_dict['promise_timeout']), promise_timeout=option_dict['promise_timeout'],
software_environment=software_environment),
option_dict]) option_dict])
...@@ -289,7 +300,8 @@ class Slapgrid(object): ...@@ -289,7 +300,8 @@ class Slapgrid(object):
master_ca_file=None, master_ca_file=None,
certificate_repository_path=None, certificate_repository_path=None,
console=False, console=False,
promise_timeout=3): promise_timeout=3,
software_environment=None):
"""Makes easy initialisation of class parameters""" """Makes easy initialisation of class parameters"""
# Parses arguments # Parses arguments
self.software_root = os.path.abspath(software_root) self.software_root = os.path.abspath(software_root)
...@@ -320,6 +332,7 @@ class Slapgrid(object): ...@@ -320,6 +332,7 @@ class Slapgrid(object):
self.console = console self.console = console
self.buildout = buildout self.buildout = buildout
self.promise_timeout = promise_timeout self.promise_timeout = promise_timeout
self.software_environment = software_environment
def checkEnvironmentAndCreateStructure(self): def checkEnvironmentAndCreateStructure(self):
"""Checks for software_root and instance_root existence, then creates """Checks for software_root and instance_root existence, then creates
...@@ -381,7 +394,8 @@ class Slapgrid(object): ...@@ -381,7 +394,8 @@ class Slapgrid(object):
console=self.console, buildout=self.buildout, console=self.console, buildout=self.buildout,
signature_private_key_file=self.signature_private_key_file, signature_private_key_file=self.signature_private_key_file,
upload_cache_url=self.upload_cache_url, upload_cache_url=self.upload_cache_url,
upload_dir_url=self.upload_dir_url).install() upload_dir_url=self.upload_dir_url,
software_environment=self.software_environment).install()
except (SystemExit, KeyboardInterrupt): except (SystemExit, KeyboardInterrupt):
exception = traceback.format_exc() exception = traceback.format_exc()
software_release.error(exception) software_release.error(exception)
......
...@@ -100,7 +100,7 @@ def getSoftwareUrlHash(url): ...@@ -100,7 +100,7 @@ def getSoftwareUrlHash(url):
return md5(url).hexdigest() return md5(url).hexdigest()
def getCleanEnvironment(home_path='/tmp'): def getCleanEnvironment(home_path='/tmp', replace_environment=None):
logger = logging.getLogger('CleanEnvironment') logger = logging.getLogger('CleanEnvironment')
changed_env = {} changed_env = {}
removed_env = [] removed_env = []
...@@ -112,6 +112,10 @@ def getCleanEnvironment(home_path='/tmp'): ...@@ -112,6 +112,10 @@ def getCleanEnvironment(home_path='/tmp'):
if old is not None: if old is not None:
removed_env.append(k) removed_env.append(k)
changed_env['HOME'] = env['HOME'] = home_path changed_env['HOME'] = env['HOME'] = home_path
if replace_environment is not None:
for k, v in replace_environment.iteritems():
# Note: os.path.expandvars is used in order to simulate shell expansion
changed_env[k] = env[k] = os.path.expandvars(v)
for k in sorted(changed_env.iterkeys()): for k in sorted(changed_env.iterkeys()):
logger.debug('Overriden %s = %r' % (k,changed_env[k])) logger.debug('Overriden %s = %r' % (k,changed_env[k]))
logger.debug('Removed from environement: %s' % ', '.join(sorted(removed_env))) logger.debug('Removed from environement: %s' % ', '.join(sorted(removed_env)))
...@@ -218,7 +222,7 @@ def dropPrivileges(uid, gid): ...@@ -218,7 +222,7 @@ def dropPrivileges(uid, gid):
def bootstrapBuildout(path, buildout=None, def bootstrapBuildout(path, buildout=None,
additional_buildout_parametr_list=None, console=False): additional_buildout_parametr_list=None, console=False, environment=None):
if additional_buildout_parametr_list is None: if additional_buildout_parametr_list is None:
additional_buildout_parametr_list = [] additional_buildout_parametr_list = []
logger = logging.getLogger('BuildoutManager') logger = logging.getLogger('BuildoutManager')
...@@ -259,7 +263,8 @@ def bootstrapBuildout(path, buildout=None, ...@@ -259,7 +263,8 @@ def bootstrapBuildout(path, buildout=None,
kw.update(stdout=subprocess.PIPE, stderr=subprocess.STDOUT) kw.update(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
process_handler = SlapPopen(invocation_list, process_handler = SlapPopen(invocation_list,
preexec_fn=lambda: dropPrivileges(uid, gid), preexec_fn=lambda: dropPrivileges(uid, gid),
cwd=path, env=getCleanEnvironment(pwd.getpwuid(uid).pw_dir), cwd=path, env=getCleanEnvironment(pwd.getpwuid(uid).pw_dir,
environment),
**kw **kw
) )
result = process_handler.communicate()[0] result = process_handler.communicate()[0]
...@@ -279,7 +284,8 @@ def bootstrapBuildout(path, buildout=None, ...@@ -279,7 +284,8 @@ def bootstrapBuildout(path, buildout=None,
def launchBuildout(path, buildout_binary, def launchBuildout(path, buildout_binary,
additional_buildout_parametr_list=None, console=False): additional_buildout_parametr_list=None, console=False,
environment=None):
""" Launches buildout.""" """ Launches buildout."""
logger = logging.getLogger('BuildoutManager') logger = logging.getLogger('BuildoutManager')
if additional_buildout_parametr_list is None: if additional_buildout_parametr_list is None:
...@@ -310,7 +316,8 @@ def launchBuildout(path, buildout_binary, ...@@ -310,7 +316,8 @@ def launchBuildout(path, buildout_binary,
kw.update(stdout=subprocess.PIPE, stderr=subprocess.STDOUT) kw.update(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
process_handler = SlapPopen(invocation_list, process_handler = SlapPopen(invocation_list,
preexec_fn=lambda: dropPrivileges(uid, gid), cwd=path, preexec_fn=lambda: dropPrivileges(uid, gid), cwd=path,
env=getCleanEnvironment(pwd.getpwuid(uid).pw_dir), **kw) env=getCleanEnvironment(pwd.getpwuid(uid).pw_dir, environment),
**kw)
result = process_handler.communicate()[0] result = process_handler.communicate()[0]
if console: if console:
result = 'Please consult messages above' result = 'Please consult messages above'
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment