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

Don't overwrite plugin configuration when removing/upgrading plugins #7890

Merged
merged 1 commit into from Oct 7, 2014

Conversation

dadoonet
Copy link
Member

When removing and installing again the plugin all configuration files will be removed in config/pluginname dir.
This is bad as users may have set and added specific configuration files.

We don't have yet an upgrade command which could handle this nicely.

So we remove that code for now and we will implement an upgrade method in another PR.

Related to #5064.

@dadoonet dadoonet self-assigned this Sep 26, 2014
@clintongormley clintongormley changed the title plugins: disable support for config dir Plugins: Disable support for config dir Sep 26, 2014
}
debug("Installed " + name + " into " + toLocation.getAbsolutePath());
} else {
debug("Ignoring config as previous config already exists in " + toLocation.getAbsolutePath());
Copy link
Member

Choose a reason for hiding this comment

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

Feel like this should be more significant than debug because it really indicates a form of failure in some scenarios.

Copy link
Contributor

Choose a reason for hiding this comment

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

agree... this one should have normal visibility

Copy link
Contributor

Choose a reason for hiding this comment

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

It'd be better, to only skip the config files that have the same name, not the whole directory. So for example, if currently es has a config dir that looks like this (for plugins foo):

/config/foo/bar.yml

and the new plugin that installs needs to copy two files there:

/config/foo/bar.yml
/config/foo/baz.yml

we'll skip bar.yml but we'll still copy baz.yml. This will help us a lot when we guide the user on how to upgrade - instead of telling the user, to copy & modify a bunch of files, we'll only need to tell him to modify files under config/foo

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure. I thought about it as well but did not want to complicate code as I thought the initial patch was "urgent". Going to implement that now and add more tests.

Copy link
Member Author

Choose a reason for hiding this comment

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

@uboness What about sub dirs?

If a plugin has for the first time:

/config/foo/bar/file1.yml

And

/config/foo/bar/file1.yml
/config/foo/bar/file2.yml

Should I use Files.walkFileTree to go in each subdir/file or just take care of the first level of files?

Copy link
Member

Choose a reason for hiding this comment

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

I think it's both easier and cleaner. What do you think @uboness?

Copy link
Member Author

Choose a reason for hiding this comment

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

cleaner. For sure. Easier... Hmmm... Actually creating a /config/foo.backup/ would be easier. If everyone is OK with that, I'd prefer that solution.

Copy link
Member

Choose a reason for hiding this comment

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

I'm okay with foo.backup. It would also not be hidden from non-Windows users by default.

Copy link
Contributor

Choose a reason for hiding this comment

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

I still think skipping is better tbh... otherwise the users will be more confused on how to merge the old one with the new one. I don't think the file formats will change that much... but when they do, we'll simply be able to tell them what to change in the files they already configured in order to be compatible with the new version (not sure that will even be needed, we could perhaps support both formats in the code and make it transparent).

Copy link
Contributor

Choose a reason for hiding this comment

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

@dadoonet I don't think it complicates things that much.. it's just traversing the file tree...

and yes... sub-folders need to be supported as well. so if you see a folder with the same name/path in both places, recursively merge the two by adding the new files and skipping existing ones. I'd also argue that if in the es plugin config dir there's a file that doesn't exist in the new plugin dir structure, then rename it to "<original_file_name>.<original_extension>.old" (or something like that).

@dadoonet
Copy link
Member Author

@pickypg PR updated based on your comments. So we now backup config/pluginname to config/pluginname.backup, then we remove config/pluginname and install the plugin file content.

It means that after removing and installing again the plugin, users will have to copy thei files from config/pluginname.backup to config/pluginname. Checking manually what they need to copy.

There still an issue. If you have already installed, remove and reinstall the plugin, you have created a config/pluginname.backup. If you remove and install again, it fails today as the backup directory already exists.
(A PR update is ready with a test which fails in that case).

I think we should remove the old backup directory before backup.

Also I was wondering if making a backup should not be part of the removal process instead of the install process. I think it makes more sense to backup data when we remove the plugin.

WDYT? cc @uboness

@pickypg
Copy link
Member

pickypg commented Sep 27, 2014

I'm personally more fond of this approach because I think it's clearer how to get it working again.

I'm trying to think through the two proposed versions:

  • Add in place and do not change existing files
    • Works best for users that do not change anything (no files floating around)
    • Moderately annoying, but not necessarily confusing when the config changes and the updated plugin fails because of the existing config, which could be completely unchanged from the prior release
    • Most confusing when changes have been made and other files are added
      • Particularly true if multiple plugin versions have been skipped and changes are not immediately obvious
    • Works most similarly to Elasticsearch
  • Backup existing config and replace with new
    • Works worst when nothing changes, but the existing config had been changed (forcing users to copy them back)
    • No risk of failure if no changes were made and the update adds changes (wasted file copy).
    • Less confusing when mixing updates with new files; still requires a copy if the once-existing file now has missing changes, but it makes it easier to merge them
    • Easiest to merge
    • Works differently from Elasticsearch, but does not presume that plugins are setup with proper defaults like Elasticsearch

I wonder if we should have some sort of a "force" where it skips any backups/checks and simply overwrites (the true shortcut to delete, then install).

There still an issue ... I think we should remove the old backup directory before backup.

My only fear with this approach is that users will think something got screwed up, then retry the upgrade. In doing so, they would delete the real backup.

Assuming we maintain this approach: if an existing backup still exists, then I wonder if we should force the user to delete it?

Also I was wondering if making a backup should not be part of the removal process instead of the install process. I think it makes more sense to backup data when we remove the plugin.

If someone goes through the process of removing a plugin, then I think it's their fault to not backup their config.

@dadoonet
Copy link
Member Author

After talking with @spinscale, it's actually a bad idea to move old configuration files to an old place. Because after an update, plugins will fallback to default plugin configuration instead of keeping the right configuration in place.

So, let's do the opposite:

  • 1st step: during an install, if we detect already existing config/pluginname directory, we copy plugin ZIP file content in config/pluginname.new.
  • 2nd step: could be within the same PR or in a new one, we do the same thing but file by file; it means that we copy all non existing files from the plugin to config/pluginname but each time a file already exists, we simply copy the new file to the same dir but we append a .new at the end.

This 2nd step requires more work and more tests so it could be part of a second PR after 1.4.0.Beta1 has been released (target 1.4.0).

Comments?

@pickypg
Copy link
Member

pickypg commented Sep 29, 2014

I completely agree. That makes perfect sense, and it should make it a lot easier to understand what has changed.

It does make me wonder if this is simple enough behavior to allow without user interaction or plugin interaction (enabled transformation of the configuration from within the plugin when upgrading, a la logstash transformation). As it stands -- no matter what -- some plugin will break from any of the three proposed solutions.

For 1.4.0.Beta1, we really need to be sure that we show red flags if we leave any .new files in the config directory. As long as we do that, then I am happy.

@dadoonet dadoonet removed the review label Sep 30, 2014
@dadoonet
Copy link
Member Author

Small update on this. I will send in a couple of hours an update which basically only copy files when they does not exist in config/pluginname dir or append a .new before copying when another one already exist.

Working fine so far. Just need to update the test case.

@dadoonet dadoonet added review and removed review labels Sep 30, 2014
@dadoonet
Copy link
Member Author

It's now ready for review. @spinscale Wanna look?

* @param source Source directory (for example /tmp/es/src)
* @param destination Destination directory (destination directory /tmp/es/dst)
*/
public static void copyFilesWithoutOverwriting(File source, final File destination) throws IOException {
Copy link
Contributor

Choose a reason for hiding this comment

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

can you also add fast unit tests for this method?

Copy link
Contributor

Choose a reason for hiding this comment

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

the method name does not reveal what it does (leaving .new files around), maybe have a suffix parameter?

@spinscale
Copy link
Contributor

did a quick review. Is there consensus now, that the .new suffix/impl is good for our purposes?
Still thinking that just returning a log line is valid as well... (you never need to worry, if someone changed the .new after plugin installation and doesnt want it to be overwritten, for example)

@dadoonet
Copy link
Member Author

dadoonet commented Oct 4, 2014

@spinscale I pushed a new commit. Could you check it please?

@dadoonet
Copy link
Member Author

dadoonet commented Oct 6, 2014

@pickypg Do you agree as well with what was done within this PR? Thanks for your feedback. cc @spinscale

Files.copy(file, newFile);
} catch (FileAlreadyExistsException x) {
// We ignore this
} catch (IOException x) {
Copy link
Member

Choose a reason for hiding this comment

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

FileAlreadyExistsException is an IOException and this IOException block does the same thing as doing nothing -- return CONTINUE;.

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't get it. If we have another exception than IOException, I guess it will be raised and not catch, right? Do you mean we should have only:

try {
  Files.copy(file, newFile);
} catch (FileAlreadyExistsException x) {
  // We ignore this
}
return CONTINUE;

Copy link
Member

Choose a reason for hiding this comment

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

Yes, but replace FileAlreadyExistsException with IOException to maintain the same functionality. Sorry for saying it so confusingly before.

Copy link
Member Author

Choose a reason for hiding this comment

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

Indeed. Definitely better. Stupid me. :)

@pickypg
Copy link
Member

pickypg commented Oct 6, 2014

Minor comment. Agree with the PR! LGTM

@dadoonet
Copy link
Member Author

dadoonet commented Oct 6, 2014

@pickypg @spinscale I updated based on latest comment, rebased my work on master and force pushed to my branch. My plan is to merge it tomorrow morning around 10AM CET after running all tests again.

Let me know if you think something is wrong with this PR.

Thanks!

When removing and installing again the plugin all configuration files will be removed in `config/pluginname` dir.
This is bad as users may have set and added specific configuration files.

During an install, if we detect already existing files in `config/pluginname` directory, we simply copy the new file to the same dir but we append a `.new` at the end.

Related to  elastic#5064.

(cherry picked from commit 5da028f)
(cherry picked from commit 4cb1f95)
@dadoonet dadoonet merged commit 09ff372 into elastic:master Oct 7, 2014
@dadoonet dadoonet deleted the pr/plugins-config-support branch October 7, 2014 14:23
@jpountz jpountz removed the review label Oct 21, 2014
@clintongormley clintongormley changed the title Plugins: Disable support for config dir Plugins: Don't overwrite plugin configuration when removing/upgrading plugins Nov 3, 2014
@clintongormley clintongormley added the :Core/Infra/Plugins Plugin API and infrastructure label Mar 19, 2015
@clintongormley clintongormley changed the title Plugins: Don't overwrite plugin configuration when removing/upgrading plugins Don't overwrite plugin configuration when removing/upgrading plugins Jun 6, 2015
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.

None yet

7 participants