Skip to content

Commit eb532d0

Browse files
authored
Merge pull request #3696 from boegel/ext_postinstallcmds
run post-install commands specified for a specific extension
2 parents 7123af1 + efc3980 commit eb532d0

File tree

3 files changed

+39
-13
lines changed

3 files changed

+39
-13
lines changed

easybuild/framework/easyblock.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2436,21 +2436,34 @@ def fix_shebang(self):
24362436
contents = shebang + '\n' + contents
24372437
write_file(path, contents)
24382438

2439-
def post_install_step(self):
2439+
def run_post_install_commands(self, commands=None):
24402440
"""
2441-
Do some postprocessing
2442-
- run post install commands if any were specified
2441+
Run post install commands that are specified via 'postinstallcmds' easyconfig parameter.
24432442
"""
2443+
if commands is None:
2444+
commands = self.cfg['postinstallcmds']
2445+
2446+
if commands:
2447+
self.log.debug("Specified post install commands: %s", commands)
24442448

2445-
if self.cfg['postinstallcmds'] is not None:
24462449
# make sure we have a list of commands
2447-
if not isinstance(self.cfg['postinstallcmds'], (list, tuple)):
2448-
raise EasyBuildError("Invalid value for 'postinstallcmds', should be list or tuple of strings.")
2449-
for cmd in self.cfg['postinstallcmds']:
2450+
if not isinstance(commands, (list, tuple)):
2451+
error_msg = "Invalid value for 'postinstallcmds', should be list or tuple of strings: %s"
2452+
raise EasyBuildError(error_msg, commands)
2453+
2454+
for cmd in commands:
24502455
if not isinstance(cmd, string_type):
24512456
raise EasyBuildError("Invalid element in 'postinstallcmds', not a string: %s", cmd)
24522457
run_cmd(cmd, simple=True, log_ok=True, log_all=True)
24532458

2459+
def post_install_step(self):
2460+
"""
2461+
Do some postprocessing
2462+
- run post install commands if any were specified
2463+
"""
2464+
2465+
self.run_post_install_commands()
2466+
24542467
self.fix_shebang()
24552468

24562469
lib_dir = os.path.join(self.installdir, 'lib')

easybuild/framework/extension.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,16 +105,17 @@ def __init__(self, mself, ext, extra_params=None):
105105

106106
name, version = self.ext['name'], self.ext.get('version', None)
107107

108-
# parent sanity check paths/commands are not relevant for extension
108+
# parent sanity check paths/commands and postinstallcmds are not relevant for extension
109109
self.cfg['sanity_check_commands'] = []
110110
self.cfg['sanity_check_paths'] = []
111+
self.cfg['postinstallcmds'] = []
111112

112113
# construct dict with template values that can be used
113114
self.cfg.template_values.update(template_constant_dict({'name': name, 'version': version}))
114115

115116
# Add install/builddir templates with values from master.
116-
for name in TEMPLATE_NAMES_EASYBLOCK_RUN_STEP:
117-
self.cfg.template_values[name[0]] = str(getattr(self.master, name[0], None))
117+
for key in TEMPLATE_NAMES_EASYBLOCK_RUN_STEP:
118+
self.cfg.template_values[key[0]] = str(getattr(self.master, key[0], None))
118119

119120
# list of source/patch files: we use an empty list as default value like in EasyBlock
120121
self.src = resolve_template(self.ext.get('src', []), self.cfg.template_values)
@@ -169,7 +170,7 @@ def postrun(self):
169170
"""
170171
Stuff to do after installing a extension.
171172
"""
172-
pass
173+
self.master.run_post_install_commands(commands=self.cfg.get('postinstallcmds', []))
173174

174175
@property
175176
def toolchain(self):

test/framework/toy_build.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,8 +1190,8 @@ def test_toy_patches(self):
11901190
archived_patch_file = os.path.join(repositorypath, 'toy', 'toy-0.0_fix-silly-typo-in-printf-statement.patch')
11911191
self.assertTrue(os.path.isfile(archived_patch_file))
11921192

1193-
def test_toy_extension_patches(self):
1194-
"""Test install toy that includes extensions with patches."""
1193+
def test_toy_extension_patches_postinstallcmds(self):
1194+
"""Test install toy that includes extensions with patches and postinstallcmds."""
11951195
test_ecs = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'easyconfigs', 'test_ecs')
11961196
toy_ec = os.path.join(test_ecs, 't', 'toy', 'toy-0.0.eb')
11971197
toy_ec_txt = read_file(toy_ec)
@@ -1210,13 +1210,25 @@ def test_toy_extension_patches(self):
12101210
' ("bar-0.0_fix-very-silly-typo-in-printf-statement.patch", 0),', # patch with patch level
12111211
' ("test.txt", "."),', # file to copy to build dir (not a real patch file)
12121212
' ],',
1213+
' "postinstallcmds": ["touch %(installdir)s/created-via-postinstallcmds.txt"],',
12131214
' }),',
12141215
']',
12151216
])
12161217
write_file(test_ec, test_ec_txt)
12171218

12181219
self.test_toy_build(ec_file=test_ec)
12191220

1221+
installdir = os.path.join(self.test_installpath, 'software', 'toy', '0.0')
1222+
1223+
# make sure that patches were actually applied (without them the message producded by 'bar' is different)
1224+
bar_bin = os.path.join(installdir, 'bin', 'bar')
1225+
out, _ = run_cmd(bar_bin)
1226+
self.assertEqual(out, "I'm a bar, and very very proud of it.\n")
1227+
1228+
# verify that post-install command for 'bar' extension was executed
1229+
fn = 'created-via-postinstallcmds.txt'
1230+
self.assertTrue(os.path.exists(os.path.join(installdir, fn)))
1231+
12201232
def test_toy_extension_sources(self):
12211233
"""Test install toy that includes extensions with 'sources' spec (as single-item list)."""
12221234
topdir = os.path.dirname(os.path.abspath(__file__))

0 commit comments

Comments
 (0)