-
Bug
-
Resolution: Fixed
-
Major
-
2.0-beta-1
-
Powered by SuggestiMate -
2.181
The plugin manager UI does not allow disabling or removing optional dependencies, i.e. dependencies that are declared by plugins to be not strictly necessary for their use.
This should be possible, maybe with a warning that not all features of the depending plugin will be available afterwards.
- is duplicated by
-
JENKINS-44013 Unable to uninstall plugin that is an optional dependency
-
- Resolved
-
-
JENKINS-45906 Optional dependency blocks plugin removal
-
- Closed
-
-
JENKINS-46930 Update Center prints warnings about plugins with optional deps when deleting plugins
-
- Resolved
-
- relates to
-
JENKINS-27177 There should be a command line mechanism to disable plugins
-
- Closed
-
-
JENKINS-50885 BlueOcean should have an optional dependency on JIRA plugin
-
- Resolved
-
-
JENKINS-39598 MultiSCM/config.jelly passes descriptors=null
-
- Closed
-
- links to
[JENKINS-33843] It's not possible to disable/uninstall optional dependencies
The Plugin Active Choices was fixed in the scope of the security advisories and the plugin Scriptler was declared optional. However the plugin cannot be removed via the plugin manager after Actives Choices has been updated. But the workaround worked, thanks jglick
Btw we use Jenkins version 2.85
"Me too"
Found this fault report while googling for much the same issue - I've got a fresh install of LTS Jenkins 2.89.1 and I wanted to remove a plugin I'd just added ... only to find that I couldn't because the DSL plugin "needed" it (the DSL plugin does not need it, it's an optional dependency).
Opinion: While it's really nice that Jenkins now warns me that I shouldn't remove X because Y needs it, this "hand holding" has gone too far the other way to the point where it's actually damaging our ability to do plugin administration via the WebUI.
I would suggest that, until Jenkins can differentiate between a hard dependency and an optional dependency, the UI should merely warn that disabling/removing a plugin may affect <list> other plugins.
Actual prevention of a perfectly valid use-case (of disabling/uninstalling a plugin that isn't wanted or required) is an unpleasant regression of core functionality.
i.e. I would suggest that what's required here is to:
- Urgently make this a warning instead of an absolute refusal, and also back-port that change to the LTS branch. That'll give us back the necessary functionality.
- Enhance the dependency algorithm to differentiate between hard dependencies and soft dependencies, and enhance the warning to distinguish between the two as well.
- Restore the current "disable the Uninstall button and the Enabled checkbox" functionality but only where there are hard dependencies (and even then, it'd be nice to have a "I know what I'm doing! Do it anyway." option).
FYI Where I work, we have a lot of people running Jenkins who do not have filesystem access to the server that's running their Jenkins service - they have admin-access to the Jenkins WebUI, but not the underlying server's filesystem - so the suggested workaround isn't going to be easy for those folks. We also have a security dept mandating that we use Jenkins 2.46.2 or later, so we can't use a version of Jenkins that doesn't have this bug either.
My guess (also untested) is that one could also work around this by using the Script Console and telling it to run code like this:
final String pluginToRemove = 'Foo'
final String pluginDir = Jenkins.getInstance().pluginManager.rootDir
final File pluginFile = new File(pluginDir, pluginToRemove + '.hpi')
if (pluginFile.delete()) {
println( pluginFile + ' deleted.' )
}
+1
Trying to simplify by removing unneeded plugins is just not possible. I don't even know why the Green Balls plugin has the LDAP plugin listed as an optional dependency, but it means I can't drop the LDAP one.
Enhance the dependency algorithm to differentiate between hard dependencies and soft dependencies
Jenkins has long made that distinction. It just was not being honored in this feature.
it'd be nice to have a "I know what I'm doing! Do it anyway." option
Would be useless since Jenkins core will refuse to even load a plugin which is missing a hard dependency.
I don't even know why the Green Balls plugin has the LDAP plugin listed as an optional dependency
This is because it was a plugin split out of core, and for compatibility reasons these are made implicit optional dependencies of all other plugins which were built against a version of core predating that split.
But this brings up an important point. Why are these implicit dependencies optional? Well, in the vast majority of cases the old plugin was not actually using the detached functionality, so we do not want to prevent the split plugin from being disabled or uninstalled if it is obviously unused. There are a few cases where something was detached which a number of other plugins actually relied on—the most prominent cases being maven-plugin, matrix-project, and junit—and so there is some risk that an admin would accidentally disable an “optional” dep that was actually critical to some still-enabled plugin’s functioning, typically seen as a NoClassDefFoundError at runtime. Those cases which are not already mitigated by use of @Extension(optional = true) or other defensive coding patterns can be addressed merely by releasing a downstream plugin update which builds against a newer version of Jenkins core: the Maven build will fail until the split plugin is added as a dependency to the POM, causing it to appear as a hard dependency in the binary plugin’s manifest.
The following example
Jenkins.instance.pluginManager.plugins.sort(false, {it.shortName}).each {p -> println(p.shortName); println(" dependencies:"); println(" unspecified: ${p.dependencies*.shortName.sort()}"); println(" optional: ${p.optionalDependencies*.shortName.sort()}"); println(" mandatory: ${(p.dependencies - p.optionalDependencies)*.shortName.sort()}"); println(" dependents:"); println(" unspecified: ${p.dependents.sort()}"); println(" optional: ${p.optionalDependents.sort()}"); println(" mandatory: ${(p.dependents - p.optionalDependents).sort()}"); }; null
reveals a mess:
antisamy-markup-formatter dependencies: unspecified: [bouncycastle-api, command-launcher, jdk-tool, junit] optional: [bouncycastle-api, command-launcher, jdk-tool, junit] mandatory: [] dependents: unspecified: [greenballs, uno-choice] optional: [] mandatory: [greenballs, uno-choice] bouncycastle-api dependencies: unspecified: [command-launcher, jdk-tool] optional: [command-launcher, jdk-tool] mandatory: [] dependents: unspecified: [antisamy-markup-formatter, credentials, external-monitor-job, greenballs, junit, ldap, mailer, matrix-project, windows-slaves] optional: [] mandatory: [antisamy-markup-formatter, credentials, external-monitor-job, greenballs, junit, ldap, mailer, matrix-project, windows-slaves] command-launcher dependencies: unspecified: [jdk-tool, script-security] optional: [jdk-tool] mandatory: [script-security] dependents: unspecified: [antisamy-markup-formatter, bouncycastle-api, config-file-provider, credentials, external-monitor-job, greenballs, junit, ldap, mailer, matrix-project, scm-api, ssh-credentials, structs, uno-choice, windows-slaves] optional: [] mandatory: [antisamy-markup-formatter, bouncycastle-api, config-file-provider, credentials, external-monitor-job, greenballs, junit, ldap, mailer, matrix-project, scm-api, ssh-credentials, structs, uno-choice, windows-slaves] config-file-provider dependencies: unspecified: [command-launcher, credentials, jdk-tool, ssh-credentials, structs, token-macro] optional: [cloudbees-folder, command-launcher, jdk-tool] mandatory: [credentials, ssh-credentials, structs, token-macro] dependents: unspecified: [job-dsl] optional: [job-dsl] mandatory: [] credentials dependencies: unspecified: [bouncycastle-api, command-launcher, jdk-tool, structs] optional: [bouncycastle-api, command-launcher, jdk-tool] mandatory: [structs] dependents: unspecified: [config-file-provider, ssh-credentials] optional: [] mandatory: [config-file-provider, ssh-credentials] display-url-api dependencies: unspecified: [jdk-tool] optional: [jdk-tool] mandatory: [] dependents: unspecified: [mailer] optional: [] mandatory: [mailer] external-monitor-job dependencies: unspecified: [bouncycastle-api, command-launcher, jdk-tool] optional: [bouncycastle-api, command-launcher, jdk-tool] mandatory: [] dependents: unspecified: [greenballs] optional: [] mandatory: [greenballs] greenballs dependencies: unspecified: [antisamy-markup-formatter, bouncycastle-api, command-launcher, external-monitor-job, jdk-tool, junit, ldap, mailer, matrix-auth, matrix-project, pam-auth, windows-slaves] optional: [antisamy-markup-formatter, bouncycastle-api, command-launcher, external-monitor-job, jdk-tool, junit, ldap, mailer, matrix-auth, matrix-project, pam-auth, windows-slaves] mandatory: [] dependents: unspecified: [] optional: [] mandatory: [] jdk-tool dependencies: unspecified: [] optional: [] mandatory: [] dependents: unspecified: [antisamy-markup-formatter, bouncycastle-api, command-launcher, config-file-provider, credentials, display-url-api, external-monitor-job, greenballs, junit, ldap, mailer, matrix-project, scm-api, script-security, ssh-credentials, structs, uno-choice, windows-slaves] optional: [] mandatory: [antisamy-markup-formatter, bouncycastle-api, command-launcher, config-file-provider, credentials, display-url-api, external-monitor-job, greenballs, junit, ldap, mailer, matrix-project, scm-api, script-security, ssh-credentials, structs, uno-choice, windows-slaves] job-dsl dependencies: unspecified: [config-file-provider, script-security, structs] optional: [config-file-provider, configuration-as-code, managed-scripts, vsphere-cloud] mandatory: [script-security, structs] dependents: unspecified: [] optional: [] mandatory: [] junit dependencies: unspecified: [bouncycastle-api, command-launcher, jdk-tool, script-security, structs, workflow-api, workflow-step-api] optional: [bouncycastle-api, command-launcher, jdk-tool] mandatory: [script-security, structs, workflow-api, workflow-step-api] dependents: unspecified: [antisamy-markup-formatter, greenballs, matrix-project] optional: [] mandatory: [antisamy-markup-formatter, greenballs, matrix-project] ldap dependencies: unspecified: [bouncycastle-api, command-launcher, jdk-tool, mailer] optional: [bouncycastle-api, command-launcher, jdk-tool] mandatory: [mailer] dependents: unspecified: [greenballs] optional: [] mandatory: [greenballs] mailer dependencies: unspecified: [bouncycastle-api, command-launcher, display-url-api, jdk-tool] optional: [bouncycastle-api, command-launcher, jdk-tool] mandatory: [display-url-api] dependents: unspecified: [greenballs, ldap] optional: [] mandatory: [greenballs, ldap] matrix-auth dependencies: unspecified: [] optional: [cloudbees-folder, configuration-as-code] mandatory: [] dependents: unspecified: [greenballs] optional: [] mandatory: [greenballs] matrix-project dependencies: unspecified: [bouncycastle-api, command-launcher, jdk-tool, junit, script-security] optional: [bouncycastle-api, command-launcher, jdk-tool] mandatory: [junit, script-security] dependents: unspecified: [greenballs] optional: [] mandatory: [greenballs] pam-auth dependencies: unspecified: [] optional: [] mandatory: [] dependents: unspecified: [greenballs] optional: [] mandatory: [greenballs] scm-api dependencies: unspecified: [command-launcher, jdk-tool, structs] optional: [command-launcher, jdk-tool] mandatory: [structs] dependents: unspecified: [workflow-api] optional: [] mandatory: [workflow-api] script-security dependencies: unspecified: [jdk-tool] optional: [jdk-tool] mandatory: [] dependents: unspecified: [command-launcher, job-dsl, junit, matrix-project, uno-choice] optional: [] mandatory: [command-launcher, job-dsl, junit, matrix-project, uno-choice] ssh-credentials dependencies: unspecified: [command-launcher, credentials, jdk-tool] optional: [command-launcher, jdk-tool] mandatory: [credentials] dependents: unspecified: [config-file-provider] optional: [] mandatory: [config-file-provider] structs dependencies: unspecified: [command-launcher, jdk-tool] optional: [command-launcher, jdk-tool] mandatory: [] dependents: unspecified: [config-file-provider, credentials, job-dsl, junit, scm-api, token-macro, workflow-api, workflow-step-api] optional: [] mandatory: [config-file-provider, credentials, job-dsl, junit, scm-api, token-macro, workflow-api, workflow-step-api] token-macro dependencies: unspecified: [structs, workflow-step-api] optional: [] mandatory: [structs, workflow-step-api] dependents: unspecified: [config-file-provider] optional: [] mandatory: [config-file-provider] uno-choice dependencies: unspecified: [antisamy-markup-formatter, command-launcher, jdk-tool, script-security] optional: [command-launcher, jdk-tool, scriptler] mandatory: [antisamy-markup-formatter, script-security] dependents: unspecified: [] optional: [] mandatory: [] windows-slaves dependencies: unspecified: [bouncycastle-api, command-launcher, jdk-tool] optional: [bouncycastle-api, command-launcher, jdk-tool] mandatory: [] dependents: unspecified: [greenballs] optional: [] mandatory: [greenballs] workflow-api dependencies: unspecified: [scm-api, structs, workflow-step-api] optional: [] mandatory: [scm-api, structs, workflow-step-api] dependents: unspecified: [junit] optional: [] mandatory: [junit] workflow-step-api dependencies: unspecified: [structs] optional: [] mandatory: [structs] dependents: unspecified: [junit, token-macro, workflow-api] optional: [] mandatory: [junit, token-macro, workflow-api]
First of all, dependencies usually includes those entries in optionalDependencies, but not in all cases.
More to the point for this issue, dependents in fact includes optional dependents. Also, optionalDependents for detached plugins lacks implied optional dependencies.
Also I think I saw that some of the values change from a Jenkins session in which a plugin is newly installed from the update center and dynamically loaded to a session after the restart.
I am removing the newbie-friendly label since it seems to be anything but: the GUI actually looks OK, it is the data model which is all wrong.
At least the optionalDependents field was introduced in JENKINS-27177. It seems that the use of dependents to mean all dependencies predated that. Hard to tell what the original intent was, since the Javadoc does not specify; some of this seems to date to Jenkins 2.0.
Great news that this is resolved. Which version will have this fixed?
(I see it in Jenkins ver. 2.164.2 where I can't uninstall Static Analysis Utilities 1.96 (which has a security warning and is end-of-life) due to an optional dependency to it from Email Extension Plugin 2.66 which I still use)
Are you sure? analysis-core 1.96 should not have a security warning, we fixed that issue.
costescuandrei the fix is still open for review. If and when the fix is merged, this issue will be closed with details. In the meantime, see the *.disabled workaround above.
danielbeck FWIW, analysis-core 1.96 still shows the security warning:
We first saw the warning with 1.95 installed, upgraded, and still see it.
medianick Thanks. Looks like I typoed the versions regex, fixed in https://github.com/jenkins-infra/update-center2/pull/273
I am postponing backport of this fix to give it some more soaking time.
In case it's helpful to anyone else (as I've just gone through this to uninstall Mask Passwords due to SECURITY-157), jglick's workaround disables the optional dependency in question (mask-passwords.jpi in my case), after which point the Uninstall button in the Manage Plugins page will enable, and the plugin can be uninstalled as desired.
This change seems to allow now to also uninstall/disable implied plugins. So release 2.176.2 introduced with JENKINS-57528 the change that all implied plugins are also installed, and now I can uninstall them again manually?
Or disable them, yes. Really it might be better for Docker image users to have an alternate distribution of jenkins.war without any detached plugins.
Workaround (untested): touch $JENKINS_HOME/plugins/unwanted.jpi.disabled