Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for backing up modules with --module-only via --backup-modules #2134

Merged
merged 28 commits into from
Aug 21, 2017

Conversation

damianam
Copy link
Member

With this PR easybuild will create a backup of existing modules when using --modules-only. 2 extra comments:

  1. While I was at it, I also used the new back_up_file function to rotate logs
  2. I think it makes sense to print the diff of modules in stdout. Thoughts?

@boegel boegel modified the milestone: 3.2.0 Feb 28, 2017
@boegel
Copy link
Member

boegel commented Apr 26, 2017

@damianam This needs more work (e.g. review & tests), and since neither of us will have time to work on this in the coming days, let's bump the milestone to 3.3.0 on this and revisit it later.

@boegel boegel modified the milestones: 3.3.0, 3.2.0 Apr 26, 2017
@damianam
Copy link
Member Author

@boegel take a look when you can. I'll see if tomorrow I can write some tests for it.

if module_only and os.path.exists(mod_filepath):
warning_msg = "Old module file found. Backing it up in %s. Diff is:\n%s"
mod_bck_filepath = back_up_file(mod_filepath, backup_extension="bck")
(mod_diff, _) = run_cmd("diff %s %s" % (mod_bck_filepath, mod_filepath))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use diff -u?

module_only = build_option('module_only')
if module_only and os.path.exists(mod_filepath):
warning_msg = "Old module file found. Backing it up in %s. Diff is:\n%s"
mod_bck_filepath = back_up_file(mod_filepath, backup_extension="bck")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should make this a hidden module, no?

also, this should be configurable, people should be able to disable the backup if they're confident enough (but I guess having it enabled by default makes sense)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making it a hidden module makes sense just for TCL modules. I had lua modules in mind, but since there are still people out there with TCL modules I agree with you.

Regarding making it configurable..... I am not so sure.

Pros:

  1. Flexibility.

Cons:

  1. Yet another option cluttering the --help
  2. More code to maintain

However, if you are using TCL modules with Lmod, these will be recognized as modules that can be loaded, which is not what you want. Any other combination (TCL modules with Tmod, or lua modules with Lmod), will result in an invisible (to the modules tool) backup. So yes, I guess I should also prepare an option for it.....


# remove first to ensure portability
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clarify portability?



def back_up_file(src_file, backup_extension=""):
"""Backs up a file appending a backup extension and a number to it. Returns the name of the backup"""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clarify: the number is optional (only when existing backups are already there)

use :param: to document arguments

also support hide named argument to backup to a hidden file

@boegel
Copy link
Member

boegel commented Jun 15, 2017

@damianam For functions you touch/change, please check whether they have a dedicated unit test already (and maybe enhance it while you're at it).

When adding new functions, add a dedicated test for them.

@damianam
Copy link
Member Author

@boegel I addressed all your comments. The code hasn't been tested yet, and the tests are still missing, but most of the bits and pieces should be there already.

@damianam damianam changed the title Backup modules (WIP) Backup modules Jul 18, 2017
…dule. Written full tests for that functionality.
@damianam damianam changed the title (WIP) Backup modules Backup modules Jul 19, 2017
@damianam
Copy link
Member Author

Tests are complete and code seems to be working. @easybuilders/easybuild-framework-maintainers please review.

@easybuilders easybuilders deleted a comment from boegelbot Aug 11, 2017
@@ -718,6 +720,10 @@ def postprocess(self):
build_easyconfig_constants_dict() # runs the easyconfig constants sanity check
self._postprocess_list_avail()

# if --backup-modules is used without --module-only print a warning
if self.options.backup_modules and not self.options.module_only:
print_warning("--backup-modules can be used just together with --module-only. Ignoring it...")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd make this an error instead?

@@ -494,6 +494,53 @@ def test_guess_patch_level(self):
]:
self.assertEqual(ft.guess_patch_level([patched_file], self.test_buildpath), correct_patch_level)

def test_back_up_file(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing additional tests for find_backup_name_candidate and move_file?

elif build_option('force') or build_option('rebuild'):
if os.path.exists(self.mod_filepath):
if os.path.exists(self.mod_filepath) and not build_option('backup_modules'):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rather than simply not removing, shouldn't we be renaming the module here already to its backup name?

else:
self.log.info(warning_msg + ' No differences found.', mod_bck_filepath)
print_warning(warning_msg % mod_bck_filepath + ' No differences found.')
self.log.info("Module file %s written: %s", mod_filepath, txt)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this whole block is rather big to just shove it into make_module_step like this, it's better to move it into a separate method named back_up_existing_module_file or something like that?

warning_msg = "Old module file found. Backing it up in %s."
hidden = False
if isinstance(self.module_generator, ModuleGeneratorTcl):
hidden = True
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indent is off here?

Also, why only do hidden for Tcl modules?

The backup should always be a hidden module imho, you don't want to expose the backup module to users?

Maybe we should also back up outside of the module tree, e.g. in the current directory (or at a location specified via --backup-modules?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because lua modules have to end in .lua, otherwise they aren't treated as modules by Lmod, and don't show up with ml av. So there is no need to keep them hidden since the backup extension avoids that file ends in .lua.

Tcl modules on the other need to be hidden. Which is not that nice, since Lmod can still show them with --show-hidden. But that's the best compromise IMO. The alternative would be to remove the module header.

Backing up outside of the module tree kind of defeats the purpose of the backup. In my opinion the backup should be used for quick verification of the changes and for doing a "rollback" if necessary. If I have the current module and the backup in different files it slightly makes it more complicated and cumbersome, and more difficult to directly see if there was a previous version at any point with a simple ls

stderr = self.get_stderr()
self.mock_stderr(False)
self.assertTrue(os.path.exists(toy_mod))
self.assertTrue(os.path.exists(os.path.join(os.path.dirname(toy_mod), '.'+os.path.basename(toy_mod)+'.bck')))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use os.path.split & os.path.join, spaces around +

self.eb_main(args + ['--backup-modules'], do_build=True, raise_error=True, verbose=True)
stderr = self.get_stderr()
self.mock_stderr(False)
self.assertTrue(os.path.exists(os.path.join(os.path.dirname(toy_mod), '.'+os.path.basename(toy_mod)+'.bck_0')))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use os.path.split & os.path.join, spaces around +

warning = "WARNING: Old module file found. Backing it up in .* Diff is:"
diff = "some difference\n"
with open(toy_mod, "a") as fh:
fh.write(diff)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use write_file (it has an append mode)

]
args = common_args + ['--module-syntax=Tcl']

warning = "WARNING: Old module file found. Backing it up in .* No differences found"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, should this be a warning? It's just an informative message, no?

if isinstance(self.modtool, Lmod):
args = common_args + ['--module-syntax=Lua']

toy_mod = os.path.join(self.test_installpath, 'modules', 'all', 'toy', '0.0-deps.lua')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rather than copy-pasting all the checks, we should hoist them in a helper function, and simplify the test to

def test_backup_modules(self):
    """Test use of --backup-modules."""
    def run_checks():
        ...

    ...

    toy_mod_fn = '0.0-deps'
    run_checks()

    if isinstance(self.modtool, Lmod):
      toy_mod_fn = '0.0-deps.lua'
      run_checks()

@boegel boegel changed the title Backup modules add support for backing up modules with --module-only via --backup-modules Aug 17, 2017
boegel and others added 4 commits August 18, 2017 14:35
…gure step to ensure identical module under --module-only
…s under --module-only & --skip + enhance/fix test_backup_modules
rework support for --backup-modules
@easybuilders easybuilders deleted a comment from boegelbot Aug 21, 2017
Copy link
Member

@boegel boegel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@boegel
Copy link
Member

boegel commented Aug 21, 2017

Going in, thanks @damianam!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants