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
Conversation
} | ||
debug("Installed " + name + " into " + toLocation.getAbsolutePath()); | ||
} else { | ||
debug("Ignoring config as previous config already exists in " + toLocation.getAbsolutePath()); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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).
@pickypg PR updated based on your comments. So we now backup It means that after removing and installing again the plugin, users will have to copy thei files from There still an issue. If you have already installed, remove and reinstall the plugin, you have created a 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 |
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:
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).
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?
If someone goes through the process of removing a plugin, then I think it's their fault to not backup their config. |
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:
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? |
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 |
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 Working fine so far. Just need to update the test case. |
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 { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
did a quick review. Is there consensus now, that the |
@spinscale I pushed a new commit. Could you check it please? |
@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) { |
There was a problem hiding this comment.
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;
.
There was a problem hiding this comment.
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;
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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. :)
Minor comment. Agree with the PR! LGTM |
a004168
to
248f74d
Compare
@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)
248f74d
to
09ff372
Compare
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.