Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[JENKINS-28041] Extended delete-view CLI command to accept multiple n…
…ames to delete
  • Loading branch information
pjanouse committed May 7, 2015
1 parent 1c78152 commit 4ddc5aa
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 19 deletions.
92 changes: 77 additions & 15 deletions core/src/main/java/hudson/cli/DeleteViewCommand.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
* Copyright (c) 2013 Red Hat, Inc.
* Copyright (c) 2013-5 Red Hat, 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
Expand All @@ -27,17 +27,22 @@
import hudson.model.ViewGroup;
import hudson.model.View;

import jenkins.model.Jenkins;
import org.kohsuke.args4j.Argument;

import java.util.HashSet;
import java.util.List;
import java.util.StringTokenizer;

/**
* @author ogondza
* @author ogondza, pjanouse
* @since 1.538
*/
@Extension
public class DeleteViewCommand extends CLICommand {

@Argument(usage="Name of the view to delete", required=true)
private View view;
@Argument(usage="View names to delete", required=true, multiValued=true)
private List<String> views;

@Override
public String getShortDescription() {
Expand All @@ -48,20 +53,77 @@ public String getShortDescription() {
@Override
protected int run() throws Exception {

view.checkPermission(View.DELETE);
boolean errorOccurred = false;

final ViewGroup group = view.getOwner();
if (!group.canDelete(view)) {
// Remove duplicates
HashSet<String> hs = new HashSet<String>();
hs.addAll(views);

stderr.format("%s does not allow to delete '%s' view\n",
group.getDisplayName(),
view.getViewName()
);
return -1;
}
for(String view_s : hs) {
View view = null;

ViewGroup group = Jenkins.getInstance();

final StringTokenizer tok = new StringTokenizer(view_s, "/");
while (tok.hasMoreTokens()) {
String viewName = tok.nextToken();

view = group.getView(viewName);
if (view == null) {
stderr.format("No view named %s inside view %s", viewName, group.getDisplayName());
errorOccurred = true;
break;
}

group.deleteView(view);;
try {
view.checkPermission(View.READ);
} catch (Exception e) {
stderr.println(e.getMessage());
errorOccurred = true;
view = null;
break;
}

return 0;
if (view instanceof ViewGroup) {
group = (ViewGroup) view;
} else if (tok.hasMoreTokens()) {
stderr.format("%s view can not contain views", view.getViewName());
view = null;
break;
}
}

if(view ==null)
continue;

try {
view.checkPermission(View.DELETE);
} catch (Exception e) {
stderr.println(e.getMessage());
errorOccurred = true;
continue;
}

try {
group = view.getOwner();
if (!group.canDelete(view)) {
stderr.format("%s does not allow to delete '%s' view\n",
group.getDisplayName(),
view.getViewName()
);
errorOccurred = true;
continue;
} else {
group.deleteView(view);
}
} catch (Exception e) {
stderr.format("Unexpected exception occurred during deletion of view '%s': %s\n",
view.getViewName(),
e.getMessage()
);
errorOccurred = true;
}
}
return errorOccurred ? -1 : 0;
}
}
2 changes: 1 addition & 1 deletion core/src/main/resources/hudson/cli/Messages.properties
Expand Up @@ -21,7 +21,7 @@ CreateViewCommand.ShortDescription=\
DeleteBuildsCommand.ShortDescription=\
Deletes build record(s).
DeleteViewCommand.ShortDescription=\
Deletes view.
Deletes view(s).
GroovyCommand.ShortDescription=\
Executes the specified Groovy script.
GroovyshCommand.ShortDescription=\
Expand Down
90 changes: 87 additions & 3 deletions test/src/test/java/hudson/cli/DeleteViewCommandTest.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
* Copyright 2013 Red Hat, Inc.
* Copyright 2013-5 Red Hat, 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
Expand All @@ -27,10 +27,9 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.Matchers.notNullValue;

import static hudson.cli.CLICommandInvoker.Matcher.hasNoStandardOutput;
import static hudson.cli.CLICommandInvoker.Matcher.hasNoErrorOutput;
import static hudson.cli.CLICommandInvoker.Matcher.succeeded;
import static hudson.cli.CLICommandInvoker.Matcher.succeededSilently;
import static hudson.cli.CLICommandInvoker.Matcher.failedWith;

Expand All @@ -45,6 +44,10 @@
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;

/**
* @author ??, pjanouse
* @since TODO
*/
public class DeleteViewCommandTest {

private CLICommandInvoker command;
Expand All @@ -70,6 +73,20 @@ public class DeleteViewCommandTest {
assertThat(result.stderr(), containsString("user is missing the View/Delete permission"));
}

@Test public void deleteViewShouldFailWithoutViewReadPermission() throws IOException {

j.jenkins.addView(new ListView("aView"));

final CLICommandInvoker.Result result = command
.authorizedTo(View.DELETE, Jenkins.READ)
.invokeWithArgs("aView")
;

assertThat(result, failedWith(-1));
assertThat(result, hasNoStandardOutput());
assertThat(result.stderr(), containsString("user is missing the View/Read permission"));
}

@Test public void deleteViewShouldSucceed() throws Exception {

j.jenkins.addView(new ListView("aView"));
Expand Down Expand Up @@ -105,6 +122,73 @@ public class DeleteViewCommandTest {

assertThat(result, failedWith(-1));
assertThat(result, hasNoStandardOutput());
assertThat(j.jenkins.getView("All"), notNullValue());
assertThat(result.stderr(), containsString("Jenkins does not allow to delete 'All' view"));
}

@Test public void deleteViewManyShouldSucceed() throws Exception {

j.jenkins.addView(new ListView("aView1"));
j.jenkins.addView(new ListView("aView2"));
j.jenkins.addView(new ListView("aView3"));

final CLICommandInvoker.Result result = command
.authorizedTo(View.READ, View.DELETE, Jenkins.READ)
.invokeWithArgs("aView1", "aView2", "aView3");

assertThat(result, succeededSilently());
assertThat(j.jenkins.getView("aView1"), nullValue());
assertThat(j.jenkins.getView("aView2"), nullValue());
assertThat(j.jenkins.getView("aView3"), nullValue());
}

@Test public void deleteViewManyShouldFailIfAViewDoesNotExist() throws Exception {

j.jenkins.addView(new ListView("aView1"));
j.jenkins.addView(new ListView("aView2"));

final CLICommandInvoker.Result result = command
.authorizedTo(View.READ, View.DELETE, Jenkins.READ)
.invokeWithArgs("aView1", "aView2", "never_created");

assertThat(result, failedWith(-1));
assertThat(result, hasNoStandardOutput());
assertThat(result.stderr(), containsString("No view named never_created inside view Jenkins"));

assertThat(j.jenkins.getView("aView1"), nullValue());
assertThat(j.jenkins.getView("aView2"), nullValue());
assertThat(j.jenkins.getView("never_created"), nullValue());
}

@Test public void deleteViewManyShouldSucceedEvenAViewSpecifiedTwice() throws Exception {

j.jenkins.addView(new ListView("aView1"));
j.jenkins.addView(new ListView("aView2"));

final CLICommandInvoker.Result result = command
.authorizedTo(View.READ, View.DELETE, Jenkins.READ)
.invokeWithArgs("aView1", "aView2", "aView1");

assertThat(result, succeededSilently());
assertThat(j.jenkins.getView("aView1"), nullValue());
assertThat(j.jenkins.getView("aView2"), nullValue());
}

@Test public void deleteViewManyShouldFailWithoutViewDeletePermissionButOthersShouldBeDeleted() throws Exception {

j.jenkins.addView(new ListView("aView1"));
j.jenkins.addView(new ListView("aView2"));

final CLICommandInvoker.Result result = command
.authorizedTo(View.READ, View.DELETE, Jenkins.READ)
.invokeWithArgs("aView1", "aView2", "All");

assertThat(result, failedWith(-1));
assertThat(result, hasNoStandardOutput());
assertThat(result.stderr(), containsString("Jenkins does not allow to delete 'All' view"));

assertThat(j.jenkins.getView("aView1"), nullValue());
assertThat(j.jenkins.getView("aView2"), nullValue());
assertThat(j.jenkins.getView("All"), notNullValue());
}
}

0 comments on commit 4ddc5aa

Please sign in to comment.