提交 199a8303 编写于 作者: M Matt Sicker 提交者: Oleg Nenashev

[JENKINS-52822] Add CLI command to enable a plugin (#3571)

* [JENKINS-52822] Add CLI command to enable a plugin

* [JENKINS-52822] Add CLI command to enable a plugin

This adds the ability to enable multiple plugins at once along with their dependencies.

* Add missing license headers

* Clarify javadoc

* Fix copyright

Work was done while at work!

* Improve short description of enable-plugin command

* Improve output of enable-plugin command

* Clarify enable-plugin errors regarding dependencies
上级 fe2fa9c6
/*
* The MIT License
*
* Copyright (c) 2018 CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.cli;
import hudson.Extension;
import hudson.PluginManager;
import hudson.PluginWrapper;
import jenkins.model.Jenkins;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;
import java.io.IOException;
import java.util.List;
/**
* Enables one or more installed plugins. The listed plugins must already be installed along with its dependencies.
* Any listed plugin with disabled dependencies will have its dependencies enabled transitively. Note that enabling an
* already enabled plugin does nothing.
*
* @since TODO
*/
@Extension
public class EnablePluginCommand extends CLICommand {
@Argument(required = true, usage = "Enables the plugins with the given short names and their dependencies.")
private List<String> pluginNames;
@Option(name = "-restart", usage = "Restart Jenkins after enabling plugins.")
private boolean restart;
@Override
public String getShortDescription() {
return Messages.EnablePluginCommand_ShortDescription();
}
@Override
protected int run() throws Exception {
Jenkins jenkins = Jenkins.get();
jenkins.checkPermission(Jenkins.ADMINISTER);
PluginManager manager = jenkins.getPluginManager();
for (String pluginName : pluginNames) {
enablePlugin(manager, pluginName);
}
if (restart) {
jenkins.safeRestart();
}
return 0;
}
private void enablePlugin(PluginManager manager, String shortName) throws IOException {
PluginWrapper plugin = manager.getPlugin(shortName);
if (plugin == null) {
throw new IllegalArgumentException(Messages.EnablePluginCommand_NoSuchPlugin(shortName));
}
if (plugin.isEnabled()) {
return;
}
stdout.println(String.format("Enabling plugin `%s' (%s)", plugin.getShortName(), plugin.getVersion()));
enableDependencies(manager, plugin);
plugin.enable();
stdout.println(String.format("Plugin `%s' was enabled.", plugin.getShortName()));
}
private void enableDependencies(PluginManager manager, PluginWrapper plugin) throws IOException {
for (PluginWrapper.Dependency dep : plugin.getDependencies()) {
PluginWrapper dependency = manager.getPlugin(dep.shortName);
if (dependency == null) {
throw new IllegalArgumentException(Messages.EnablePluginCommand_MissingDependencies(plugin.getShortName(), dep));
}
if (!dependency.isEnabled()) {
enableDependencies(manager, dependency);
stdout.println(String.format("Enabling plugin dependency `%s' (%s) for `%s'", dependency.getShortName(), dependency.getVersion(), plugin.getShortName()));
dependency.enable();
}
}
}
}
......@@ -7,6 +7,9 @@ InstallPluginCommand.NoUpdateCenterDefined=Note that no update center is defined
InstallPluginCommand.NoUpdateDataRetrieved=No update center data is retrieved yet from: {0}
InstallPluginCommand.NotAValidSourceName={0} is neither a valid file, URL, nor a plugin artifact name in the update center
EnablePluginCommand.NoSuchPlugin=No such plugin found with the name {0}
EnablePluginCommand.MissingDependencies=Cannot enable plugin {0} as it is missing the dependency {1}
AddJobToViewCommand.ShortDescription=\
Adds jobs to view.
BuildCommand.ShortDescription=\
......@@ -25,6 +28,8 @@ DeleteViewCommand.ShortDescription=\
Deletes view(s).
DeleteJobCommand.ShortDescription=\
Deletes job(s).
EnablePluginCommand.ShortDescription=\
Enables one or more installed plugins transitively.
GroovyCommand.ShortDescription=\
Executes the specified Groovy script.
GroovyshCommand.ShortDescription=\
......
/*
* The MIT License
*
* Copyright (c) 2018 CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.cli;
import hudson.PluginManager;
import hudson.PluginWrapper;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;
import java.io.IOException;
import static hudson.cli.CLICommandInvoker.Matcher.failedWith;
import static hudson.cli.CLICommandInvoker.Matcher.succeeded;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
public class EnablePluginCommandTest {
@Rule
public JenkinsRule j = new JenkinsRule();
private CLICommandInvoker.Result installTestPlugin(String name) {
return new CLICommandInvoker(j, new InstallPluginCommand())
.withStdin(EnablePluginCommandTest.class.getResourceAsStream("/plugins/" + name + ".hpi"))
.invokeWithArgs("-name", name, "-deploy", "=");
}
private CLICommandInvoker.Result enablePlugins(String... names) {
return new CLICommandInvoker(j, new EnablePluginCommand()).invokeWithArgs(names);
}
@Test
public void enableSinglePlugin() throws IOException {
String name = "token-macro";
PluginManager m = j.getPluginManager();
assertThat(m.getPlugin(name), is(nullValue()));
assertThat(installTestPlugin("token-macro"), succeeded());
PluginWrapper wrapper = m.getPlugin(name);
assertThat(wrapper, is(notNullValue()));
assertTrue(wrapper.isEnabled());
wrapper.disable();
assertFalse(wrapper.isEnabled());
assertThat(enablePlugins(name), succeeded());
assertTrue(wrapper.isEnabled());
}
@Test
public void enableInvalidPluginFails() {
assertThat(
new CLICommandInvoker(j, "enable-plugin").invokeWithArgs("foobar"), failedWith(3)
);
}
@Test
public void enableDependerEnablesDependee() throws IOException {
installTestPlugin("dependee");
installTestPlugin("depender");
PluginManager m = j.getPluginManager();
PluginWrapper depender = m.getPlugin("depender");
assertThat(depender, is(notNullValue()));
PluginWrapper dependee = m.getPlugin("dependee");
assertThat(dependee, is(notNullValue()));
depender.disable();
dependee.disable();
assertThat(enablePlugins("depender"), succeeded());
assertTrue(depender.isEnabled());
assertTrue(dependee.isEnabled());
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册