Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
jenkins
提交
b96d227f
J
jenkins
项目概览
xxadev
/
jenkins
与 Fork 源项目一致
从无法访问的项目Fork
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
jenkins
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
b96d227f
编写于
10月 26, 2013
作者:
K
Kohsuke Kawaguchi
浏览文件
操作
浏览文件
下载
差异文件
[FIXED JENKINS-19996] Support view manipulation via Jenkins CLI
Merged pull request #971.
上级
b26f4e4d
952ea0a9
变更
15
隐藏空白更改
内联
并排
Showing
15 changed file
with
1191 addition
and
6 deletion
+1191
-6
changelog.html
changelog.html
+3
-0
core/src/main/java/hudson/cli/CreateViewCommand.java
core/src/main/java/hudson/cli/CreateViewCommand.java
+76
-0
core/src/main/java/hudson/cli/DeleteViewCommand.java
core/src/main/java/hudson/cli/DeleteViewCommand.java
+67
-0
core/src/main/java/hudson/cli/GetViewCommand.java
core/src/main/java/hudson/cli/GetViewCommand.java
+55
-0
core/src/main/java/hudson/cli/UpdateViewCommand.java
core/src/main/java/hudson/cli/UpdateViewCommand.java
+55
-0
core/src/main/java/hudson/cli/handlers/ViewOptionHandler.java
.../src/main/java/hudson/cli/handlers/ViewOptionHandler.java
+111
-0
core/src/main/java/hudson/model/View.java
core/src/main/java/hudson/model/View.java
+24
-6
core/src/main/resources/hudson/cli/Messages.properties
core/src/main/resources/hudson/cli/Messages.properties
+8
-0
core/src/test/java/hudson/cli/handlers/ViewOptionHandlerTest.java
.../test/java/hudson/cli/handlers/ViewOptionHandlerTest.java
+232
-0
test/src/main/java/hudson/cli/CLICommandInvoker.java
test/src/main/java/hudson/cli/CLICommandInvoker.java
+82
-0
test/src/test/java/hudson/cli/CreateViewCommandTest.java
test/src/test/java/hudson/cli/CreateViewCommandTest.java
+136
-0
test/src/test/java/hudson/cli/DeleteViewCommandTest.java
test/src/test/java/hudson/cli/DeleteViewCommandTest.java
+111
-0
test/src/test/java/hudson/cli/GetViewCommandTest.java
test/src/test/java/hudson/cli/GetViewCommandTest.java
+97
-0
test/src/test/java/hudson/cli/UpdateViewCommandTest.java
test/src/test/java/hudson/cli/UpdateViewCommandTest.java
+103
-0
test/src/test/resources/hudson/cli/view.xml
test/src/test/resources/hudson/cli/view.xml
+31
-0
未找到文件。
changelog.html
浏览文件 @
b96d227f
...
@@ -55,6 +55,9 @@ Upcoming changes</a>
...
@@ -55,6 +55,9 @@ Upcoming changes</a>
<!-- Record your changes in the trunk here. -->
<!-- Record your changes in the trunk here. -->
<div
id=
"trunk"
style=
"display:none"
>
<!--=TRUNK-BEGIN=-->
<div
id=
"trunk"
style=
"display:none"
>
<!--=TRUNK-BEGIN=-->
<ul
class=
image
>
<ul
class=
image
>
<li
class=
rfe
>
Added CLI commands that manipulate views
(
<a
href=
"https://issues.jenkins-ci.org/browse/JENKINS-19996"
>
issue 19996
</a>
)
<li
class=
rfe
>
<li
class=
rfe
>
Improved the /cli help screen.
Improved the /cli help screen.
(
<a
href=
"https://issues.jenkins-ci.org/browse/JENKINS-20023"
>
issue 20023
</a>
)
(
<a
href=
"https://issues.jenkins-ci.org/browse/JENKINS-20023"
>
issue 20023
</a>
)
...
...
core/src/main/java/hudson/cli/CreateViewCommand.java
0 → 100644
浏览文件 @
b96d227f
/*
* The MIT License
*
* Copyright (c) 2013 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
* 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
org.kohsuke.args4j.Argument
;
import
jenkins.model.Jenkins
;
import
hudson.Extension
;
import
hudson.model.Failure
;
import
hudson.model.View
;
/**
* @author ogondza
* @since 1.538
*/
@Extension
public
class
CreateViewCommand
extends
CLICommand
{
@Argument
(
usage
=
"Name of the view to use instead of the one in XML"
)
public
String
viewName
=
null
;
@Override
public
String
getShortDescription
()
{
return
Messages
.
CreateViewCommand_ShortDescription
();
}
@Override
protected
int
run
()
throws
Exception
{
final
Jenkins
jenkins
=
Jenkins
.
getInstance
();
jenkins
.
checkPermission
(
View
.
CREATE
);
View
newView
;
try
{
newView
=
View
.
createViewFromXML
(
viewName
,
stdin
);
}
catch
(
Failure
ex
)
{
stderr
.
format
(
"Invalid view name: %s\n"
,
ex
.
getMessage
());
return
-
1
;
}
final
String
newName
=
newView
.
getViewName
();
if
(
jenkins
.
getView
(
newName
)
!=
null
)
{
stderr
.
format
(
"View '%s' already exists\n"
,
newName
);
return
-
1
;
}
jenkins
.
addView
(
newView
);
return
0
;
}
}
core/src/main/java/hudson/cli/DeleteViewCommand.java
0 → 100644
浏览文件 @
b96d227f
/*
* The MIT License
*
* Copyright (c) 2013 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
* 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.model.ViewGroup
;
import
hudson.model.View
;
import
org.kohsuke.args4j.Argument
;
/**
* @author ogondza
* @since 1.538
*/
@Extension
public
class
DeleteViewCommand
extends
CLICommand
{
@Argument
(
usage
=
"Name of the view to delete"
,
required
=
true
)
private
View
view
;
@Override
public
String
getShortDescription
()
{
return
Messages
.
DeleteViewCommand_ShortDescription
();
}
@Override
protected
int
run
()
throws
Exception
{
view
.
checkPermission
(
View
.
DELETE
);
final
ViewGroup
group
=
view
.
getOwner
();
if
(!
group
.
canDelete
(
view
))
{
stderr
.
format
(
"%s does not allow to delete '%s' view\n"
,
group
.
getDisplayName
(),
view
.
getViewName
()
);
return
-
1
;
}
group
.
deleteView
(
view
);;
return
0
;
}
}
core/src/main/java/hudson/cli/GetViewCommand.java
0 → 100644
浏览文件 @
b96d227f
/*
* The MIT License
*
* Copyright (c) 2013 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
* 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.model.View
;
import
org.kohsuke.args4j.Argument
;
/**
* @author ogondza
* @since 1.538
*/
@Extension
public
class
GetViewCommand
extends
CLICommand
{
@Argument
(
usage
=
"Name of the view to obtain"
,
required
=
true
)
private
View
view
;
@Override
public
String
getShortDescription
()
{
return
Messages
.
GetViewCommand_ShortDescription
();
}
@Override
protected
int
run
()
throws
Exception
{
view
.
checkPermission
(
View
.
READ
);
view
.
writeXml
(
stdout
);
return
0
;
}
}
core/src/main/java/hudson/cli/UpdateViewCommand.java
0 → 100644
浏览文件 @
b96d227f
/*
* The MIT License
*
* Copyright (c) 2013 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
* 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
javax.xml.transform.stream.StreamSource
;
import
hudson.Extension
;
import
hudson.model.View
;
import
org.kohsuke.args4j.Argument
;
/**
* @author ogondza
* @since 1.538
*/
@Extension
public
class
UpdateViewCommand
extends
CLICommand
{
@Argument
(
usage
=
"Name of the view to update"
,
required
=
true
)
private
View
view
;
@Override
public
String
getShortDescription
()
{
return
Messages
.
UpdateViewCommand_ShortDescription
();
}
@Override
protected
int
run
()
throws
Exception
{
view
.
updateByXml
(
new
StreamSource
(
stdin
));
return
0
;
}
}
core/src/main/java/hudson/cli/handlers/ViewOptionHandler.java
0 → 100644
浏览文件 @
b96d227f
/*
* The MIT License
*
* Copyright (c) 2013, 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
* 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.handlers
;
import
hudson.model.ViewGroup
;
import
hudson.model.View
;
import
java.util.StringTokenizer
;
import
jenkins.model.Jenkins
;
import
org.kohsuke.MetaInfServices
;
import
org.kohsuke.args4j.CmdLineException
;
import
org.kohsuke.args4j.CmdLineParser
;
import
org.kohsuke.args4j.OptionDef
;
import
org.kohsuke.args4j.spi.OptionHandler
;
import
org.kohsuke.args4j.spi.Parameters
;
import
org.kohsuke.args4j.spi.Setter
;
/**
* Refers to {@link View} by its name.
*
* <p>
* For example:
* <dl>
* <dt>my_view_name</dt><dd>refers to a top level view with given name.</dd>
* <dt>nested/inner</dt><dd>refers to a view named <tt>inner</tt> inside of a top level view group named <tt>nested</tt>.</dd>
* </dl>
*
* <p>
* View name is a non-empty sequence of {@link View} names delimited by '/'.
* Handler traverse the view names from left to right. First one is expected to
* be a top level view and all but the last one are expected to be instances of
* {@link ViewGroup}. Handler fails to resolve view provided a view with given
* name does not exist or a user was not granted {@link View.READ} permission.
*
* @author ogondza
* @since 1.538
*/
@MetaInfServices
public
class
ViewOptionHandler
extends
OptionHandler
<
View
>
{
public
ViewOptionHandler
(
CmdLineParser
parser
,
OptionDef
option
,
Setter
<
View
>
setter
)
{
super
(
parser
,
option
,
setter
);
}
@Override
public
int
parseArguments
(
Parameters
params
)
throws
CmdLineException
{
setter
.
addValue
(
getView
(
params
.
getParameter
(
0
)));
return
1
;
}
private
View
getView
(
String
name
)
throws
CmdLineException
{
View
view
=
null
;
ViewGroup
group
=
Jenkins
.
getInstance
();
final
StringTokenizer
tok
=
new
StringTokenizer
(
name
,
"/"
);
while
(
tok
.
hasMoreTokens
())
{
String
viewName
=
tok
.
nextToken
();
view
=
group
.
getView
(
viewName
);
if
(
view
==
null
)
throw
new
CmdLineException
(
owner
,
String
.
format
(
"No view named %s inside view %s"
,
viewName
,
group
.
getDisplayName
()
));
view
.
checkPermission
(
View
.
READ
);
if
(
view
instanceof
ViewGroup
)
{
group
=
(
ViewGroup
)
view
;
}
else
if
(
tok
.
hasMoreTokens
())
{
throw
new
CmdLineException
(
owner
,
view
.
getViewName
()
+
" view can not contain views"
);
}
}
return
view
;
}
@Override
public
String
getDefaultMetaVariable
()
{
return
"VIEW"
;
}
}
core/src/main/java/hudson/model/View.java
浏览文件 @
b96d227f
...
@@ -83,6 +83,7 @@ import java.io.BufferedInputStream;
...
@@ -83,6 +83,7 @@ import java.io.BufferedInputStream;
import
java.io.ByteArrayInputStream
;
import
java.io.ByteArrayInputStream
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.io.StringWriter
;
import
java.io.StringWriter
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Arrays
;
...
@@ -1044,16 +1045,13 @@ public abstract class View extends AbstractModelObject implements AccessControll
...
@@ -1044,16 +1045,13 @@ public abstract class View extends AbstractModelObject implements AccessControll
return
new
HttpResponse
()
{
return
new
HttpResponse
()
{
public
void
generateResponse
(
StaplerRequest
req
,
StaplerResponse
rsp
,
Object
node
)
throws
IOException
,
ServletException
{
public
void
generateResponse
(
StaplerRequest
req
,
StaplerResponse
rsp
,
Object
node
)
throws
IOException
,
ServletException
{
rsp
.
setContentType
(
"application/xml"
);
rsp
.
setContentType
(
"application/xml"
);
// pity we don't have a handy way to clone Jenkins.XSTREAM to temp add the omit Field
View
.
this
.
writeXml
(
rsp
.
getOutputStream
());
XStream2
xStream2
=
new
XStream2
();
xStream2
.
omitField
(
View
.
class
,
"owner"
);
xStream2
.
toXMLUTF8
(
View
.
this
,
rsp
.
getOutputStream
());
}
}
};
};
}
}
if
(
req
.
getMethod
().
equals
(
"POST"
))
{
if
(
req
.
getMethod
().
equals
(
"POST"
))
{
// submission
// submission
updateByXml
(
(
Source
)
new
StreamSource
(
req
.
getReader
()));
updateByXml
(
new
StreamSource
(
req
.
getReader
()));
return
HttpResponses
.
ok
();
return
HttpResponses
.
ok
();
}
}
...
@@ -1061,6 +1059,16 @@ public abstract class View extends AbstractModelObject implements AccessControll
...
@@ -1061,6 +1059,16 @@ public abstract class View extends AbstractModelObject implements AccessControll
return
HttpResponses
.
error
(
SC_BAD_REQUEST
,
"Unexpected request method "
+
req
.
getMethod
());
return
HttpResponses
.
error
(
SC_BAD_REQUEST
,
"Unexpected request method "
+
req
.
getMethod
());
}
}
/**
* @since 1.538
*/
public
void
writeXml
(
OutputStream
out
)
throws
IOException
{
// pity we don't have a handy way to clone Jenkins.XSTREAM to temp add the omit Field
XStream2
xStream2
=
new
XStream2
();
xStream2
.
omitField
(
View
.
class
,
"owner"
);
xStream2
.
toXMLUTF8
(
View
.
this
,
out
);
}
/**
/**
* Updates Job by its XML definition.
* Updates Job by its XML definition.
*/
*/
...
@@ -1083,7 +1091,11 @@ public abstract class View extends AbstractModelObject implements AccessControll
...
@@ -1083,7 +1091,11 @@ public abstract class View extends AbstractModelObject implements AccessControll
// try to reflect the changes by reloading
// try to reflect the changes by reloading
InputStream
in
=
new
BufferedInputStream
(
new
ByteArrayInputStream
(
out
.
toString
().
getBytes
(
"UTF-8"
)));
InputStream
in
=
new
BufferedInputStream
(
new
ByteArrayInputStream
(
out
.
toString
().
getBytes
(
"UTF-8"
)));
try
{
try
{
// Do not allow overwriting view name as it might collide with another
// view in same ViewGroup and might not satisfy Jenkins.checkGoodName.
String
oldname
=
name
;
Jenkins
.
XSTREAM
.
unmarshal
(
new
XppDriver
().
createReader
(
in
),
this
);
Jenkins
.
XSTREAM
.
unmarshal
(
new
XppDriver
().
createReader
(
in
),
this
);
name
=
oldname
;
}
catch
(
StreamException
e
)
{
}
catch
(
StreamException
e
)
{
throw
new
IOException2
(
"Unable to read"
,
e
);
throw
new
IOException2
(
"Unable to read"
,
e
);
}
catch
(
ConversionException
e
)
{
}
catch
(
ConversionException
e
)
{
...
@@ -1185,11 +1197,17 @@ public abstract class View extends AbstractModelObject implements AccessControll
...
@@ -1185,11 +1197,17 @@ public abstract class View extends AbstractModelObject implements AccessControll
return
v
;
return
v
;
}
}
/**
* Instantiate View subtype from XML stream.
*
* @param name Alternative name to use or <tt>null</tt> to keep the one in xml.
*/
public
static
View
createViewFromXML
(
String
name
,
InputStream
xml
)
throws
IOException
{
public
static
View
createViewFromXML
(
String
name
,
InputStream
xml
)
throws
IOException
{
InputStream
in
=
new
BufferedInputStream
(
xml
);
InputStream
in
=
new
BufferedInputStream
(
xml
);
try
{
try
{
View
v
=
(
View
)
Jenkins
.
XSTREAM
.
fromXML
(
in
);
View
v
=
(
View
)
Jenkins
.
XSTREAM
.
fromXML
(
in
);
v
.
name
=
name
;
if
(
name
!=
null
)
v
.
name
=
name
;
checkGoodName
(
v
.
name
);
return
v
;
return
v
;
}
catch
(
StreamException
e
)
{
}
catch
(
StreamException
e
)
{
throw
new
IOException2
(
"Unable to read"
,
e
);
throw
new
IOException2
(
"Unable to read"
,
e
);
...
...
core/src/main/resources/hudson/cli/Messages.properties
浏览文件 @
b96d227f
...
@@ -14,8 +14,12 @@ CreateJobCommand.ShortDescription=\
...
@@ -14,8 +14,12 @@ CreateJobCommand.ShortDescription=\
Creates a new job by reading stdin as a configuration XML file.
Creates a new job by reading stdin as a configuration XML file.
CreateNodeCommand.ShortDescription
=
\
CreateNodeCommand.ShortDescription
=
\
Creates a new node by reading stdin as a XML configuration.
Creates a new node by reading stdin as a XML configuration.
CreateViewCommand.ShortDescription
=
\
Creates a new view by reading stdin as a XML configuration.
DeleteBuildsCommand.ShortDescription
=
\
DeleteBuildsCommand.ShortDescription
=
\
Deletes build record(s).
Deletes build record(s).
DeleteViewCommand.ShortDescription
=
\
Deletes view.
GroovyCommand.ShortDescription
=
\
GroovyCommand.ShortDescription
=
\
Executes the specified Groovy script.
Executes the specified Groovy script.
GroovyshCommand.ShortDescription
=
\
GroovyshCommand.ShortDescription
=
\
...
@@ -49,6 +53,8 @@ GetJobCommand.ShortDescription=\
...
@@ -49,6 +53,8 @@ GetJobCommand.ShortDescription=\
Dumps the job definition XML to stdout.
Dumps the job definition XML to stdout.
GetNodeCommand.ShortDescription
=
\
GetNodeCommand.ShortDescription
=
\
Dumps the node definition XML to stdout.
Dumps the node definition XML to stdout.
GetViewCommand.ShortDescription
=
\
Dumps the view definition XML to stdout.
SetBuildDisplayNameCommand.ShortDescription
=
\
SetBuildDisplayNameCommand.ShortDescription
=
\
Sets the displayName of a build.
Sets the displayName of a build.
WhoAmICommand.ShortDescription
=
\
WhoAmICommand.ShortDescription
=
\
...
@@ -58,6 +64,8 @@ UpdateJobCommand.ShortDescription=\
...
@@ -58,6 +64,8 @@ UpdateJobCommand.ShortDescription=\
UpdateNodeCommand.ShortDescription
=
\
UpdateNodeCommand.ShortDescription
=
\
Updates the node definition XML from stdin. The opposite of the get-node command.
Updates the node definition XML from stdin. The opposite of the get-node command.
SessionIdCommand.ShortDescription
=
Outputs the session ID, which changes every time Jenkins restarts.
SessionIdCommand.ShortDescription
=
Outputs the session ID, which changes every time Jenkins restarts.
UpdateViewCommand.ShortDescription
=
\
Updates the view definition XML from stdin. The opposite of the get-view command.
BuildCommand.CLICause.ShortDescription
=
Started by command line by {0}
BuildCommand.CLICause.ShortDescription
=
Started by command line by {0}
BuildCommand.CLICause.CannotBuildDisabled
=
\
BuildCommand.CLICause.CannotBuildDisabled
=
\
...
...
core/src/test/java/hudson/cli/handlers/ViewOptionHandlerTest.java
0 → 100644
浏览文件 @
b96d227f
/*
* The MIT License
*
* Copyright (c) 2013 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
* 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.handlers
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
fail
;
import
static
org
.
mockito
.
Mockito
.
doThrow
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
verifyNoMoreInteractions
;
import
static
org
.
mockito
.
Mockito
.
verifyZeroInteractions
;
import
static
org
.
mockito
.
Mockito
.
when
;
import
hudson.model.ViewGroup
;
import
hudson.model.View
;
import
jenkins.model.Jenkins
;
import
org.acegisecurity.AccessDeniedException
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.kohsuke.args4j.CmdLineException
;
import
org.kohsuke.args4j.spi.Parameters
;
import
org.kohsuke.args4j.spi.Setter
;
import
org.mockito.Mock
;
import
org.mockito.MockitoAnnotations
;
import
org.powermock.api.mockito.PowerMockito
;
import
org.powermock.core.classloader.annotations.PrepareForTest
;
import
org.powermock.modules.junit4.PowerMockRunner
;
@PrepareForTest
(
Jenkins
.
class
)
@RunWith
(
PowerMockRunner
.
class
)
public
class
ViewOptionHandlerTest
{
@Mock
private
Setter
<
View
>
setter
;
private
ViewOptionHandler
handler
;
// Hierarchy of views used as a shared fixture:
// $JENKINS_URL/view/outer/view/nested/view/inner/
@Mock
private
View
inner
;
@Mock
private
CompositeView
nested
;
@Mock
private
CompositeView
outer
;
@Mock
private
Jenkins
jenkins
;
@Before
public
void
setUp
()
{
MockitoAnnotations
.
initMocks
(
this
);
handler
=
new
ViewOptionHandler
(
null
,
null
,
setter
);
when
(
inner
.
getViewName
()).
thenReturn
(
"inner"
);
when
(
inner
.
getDisplayName
()).
thenCallRealMethod
();
when
(
nested
.
getViewName
()).
thenReturn
(
"nested"
);
when
(
nested
.
getDisplayName
()).
thenCallRealMethod
();
when
(
nested
.
getView
(
"inner"
)).
thenReturn
(
inner
);
when
(
outer
.
getViewName
()).
thenReturn
(
"outer"
);
when
(
outer
.
getDisplayName
()).
thenCallRealMethod
();
when
(
outer
.
getView
(
"nested"
)).
thenReturn
(
nested
);
PowerMockito
.
mockStatic
(
Jenkins
.
class
);
PowerMockito
.
when
(
Jenkins
.
getInstance
()).
thenReturn
(
jenkins
);
when
(
jenkins
.
getView
(
"outer"
)).
thenReturn
(
outer
);
when
(
jenkins
.
getDisplayName
()).
thenReturn
(
"Jenkins"
);
}
@Test
public
void
resolveTopLevelView
()
throws
Exception
{
parse
(
"outer"
);
verify
(
setter
).
addValue
(
outer
);
}
@Test
public
void
resolveNestedView
()
throws
Exception
{
parse
(
"outer/nested"
);
verify
(
setter
).
addValue
(
nested
);
}
@Test
public
void
resolveOuterView
()
throws
Exception
{
parse
(
"outer/nested/inner"
);
verify
(
setter
).
addValue
(
inner
);
}
@Test
public
void
ignoreLeadingAndTrailingSlashes
()
throws
Exception
{
parse
(
"/outer/nested/inner/"
);
verify
(
setter
).
addValue
(
inner
);
}
@Test
public
void
reportNonexistentTopLevelView
()
throws
Exception
{
assertEquals
(
"No view named missing_view inside view Jenkins"
,
parseFailedWith
(
CmdLineException
.
class
,
"missing_view"
)
);
verifyZeroInteractions
(
setter
);
}
@Test
public
void
reportNonexistentNestedView
()
throws
Exception
{
assertEquals
(
"No view named missing_view inside view outer"
,
parseFailedWith
(
CmdLineException
.
class
,
"outer/missing_view"
)
);
verifyZeroInteractions
(
setter
);
}
@Test
public
void
reportNonexistentInnerView
()
throws
Exception
{
assertEquals
(
"No view named missing_view inside view nested"
,
parseFailedWith
(
CmdLineException
.
class
,
"outer/nested/missing_view"
)
);
verifyZeroInteractions
(
setter
);
}
@Test
public
void
reportTraversingViewThatIsNotAViewGroup
()
throws
Exception
{
assertEquals
(
"inner view can not contain views"
,
parseFailedWith
(
CmdLineException
.
class
,
"outer/nested/inner/missing"
)
);
verifyZeroInteractions
(
setter
);
}
@Test
public
void
refuseToReadOuterView
()
throws
Exception
{
denyAccessOn
(
outer
);
parseFailedWith
(
AccessDeniedException
.
class
,
"outer/nested/inner"
);
verify
(
outer
).
checkPermission
(
View
.
READ
);
verifyNoMoreInteractions
(
outer
);
verifyZeroInteractions
(
nested
);
verifyZeroInteractions
(
inner
);
verifyZeroInteractions
(
setter
);
}
@Test
public
void
refuseToReadNestedView
()
throws
Exception
{
denyAccessOn
(
nested
);
parseFailedWith
(
AccessDeniedException
.
class
,
"outer/nested/inner"
);
verify
(
nested
).
checkPermission
(
View
.
READ
);
verifyNoMoreInteractions
(
nested
);
verifyZeroInteractions
(
inner
);
verifyZeroInteractions
(
setter
);
}
@Test
public
void
refuseToReadInnerView
()
throws
Exception
{
denyAccessOn
(
inner
);
parseFailedWith
(
AccessDeniedException
.
class
,
"outer/nested/inner"
);
verify
(
inner
).
checkPermission
(
View
.
READ
);
verifyNoMoreInteractions
(
inner
);
verifyZeroInteractions
(
setter
);
}
private
void
denyAccessOn
(
View
view
)
{
doThrow
(
new
AccessDeniedException
(
null
)).
when
(
view
).
checkPermission
(
View
.
READ
);
}
private
String
parseFailedWith
(
Class
<?
extends
Exception
>
type
,
final
String
...
params
)
throws
Exception
{
try
{
parse
(
params
);
}
catch
(
Exception
ex
)
{
if
(!
type
.
isAssignableFrom
(
ex
.
getClass
()))
throw
ex
;
return
ex
.
getMessage
();
}
fail
(
"No exception thrown. Expected "
+
type
.
getClass
());
return
null
;
}
private
void
parse
(
final
String
...
params
)
throws
CmdLineException
{
handler
.
parseArguments
(
new
Parameters
()
{
public
String
getParameter
(
int
idx
)
throws
CmdLineException
{
return
params
[
idx
];
}
public
int
size
()
{
return
params
.
length
;
}
});
}
private
static
abstract
class
CompositeView
extends
View
implements
ViewGroup
{
protected
CompositeView
(
String
name
)
{
super
(
name
);
}
}
}
test/src/main/java/hudson/cli/CLICommandInvoker.java
浏览文件 @
b96d227f
...
@@ -24,6 +24,7 @@
...
@@ -24,6 +24,7 @@
package
hudson.cli
;
package
hudson.cli
;
import
hudson.Extension
;
import
hudson.model.User
;
import
hudson.model.User
;
import
hudson.security.Permission
;
import
hudson.security.Permission
;
import
hudson.security.GlobalMatrixAuthorizationStrategy
;
import
hudson.security.GlobalMatrixAuthorizationStrategy
;
...
@@ -31,11 +32,16 @@ import hudson.security.GlobalMatrixAuthorizationStrategy;
...
@@ -31,11 +32,16 @@ import hudson.security.GlobalMatrixAuthorizationStrategy;
import
java.io.ByteArrayOutputStream
;
import
java.io.ByteArrayOutputStream
;
import
java.io.InputStream
;
import
java.io.InputStream
;
import
java.io.PrintStream
;
import
java.io.PrintStream
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Locale
;
import
java.util.Locale
;
import
jenkins.model.Jenkins
;
import
org.hamcrest.Description
;
import
org.hamcrest.TypeSafeMatcher
;
import
org.jvnet.hudson.test.JenkinsRule
;
import
org.jvnet.hudson.test.JenkinsRule
;
/**
/**
...
@@ -56,6 +62,14 @@ public class CLICommandInvoker {
...
@@ -56,6 +62,14 @@ public class CLICommandInvoker {
public
CLICommandInvoker
(
final
JenkinsRule
rule
,
final
CLICommand
command
)
{
public
CLICommandInvoker
(
final
JenkinsRule
rule
,
final
CLICommand
command
)
{
if
(
command
.
getClass
().
getAnnotation
(
Extension
.
class
)
==
null
)
{
throw
new
AssertionError
(
String
.
format
(
"Command %s is missing @Extension annotation."
,
command
.
getClass
()
));
}
this
.
rule
=
rule
;
this
.
rule
=
rule
;
this
.
command
=
command
;
this
.
command
=
command
;
}
}
...
@@ -68,6 +82,8 @@ public class CLICommandInvoker {
...
@@ -68,6 +82,8 @@ public class CLICommandInvoker {
public
CLICommandInvoker
withStdin
(
final
InputStream
stdin
)
{
public
CLICommandInvoker
withStdin
(
final
InputStream
stdin
)
{
if
(
stdin
==
null
)
throw
new
NullPointerException
(
"No stdin provided"
);
this
.
stdin
=
stdin
;
this
.
stdin
=
stdin
;
return
this
;
return
this
;
}
}
...
@@ -151,5 +167,71 @@ public class CLICommandInvoker {
...
@@ -151,5 +167,71 @@ public class CLICommandInvoker {
return
err
.
toString
();
return
err
.
toString
();
}
}
@Override
public
String
toString
()
{
StringBuilder
builder
=
new
StringBuilder
(
"CLI command exited with "
).
append
(
result
);
String
stdout
=
stdout
();
if
(!
""
.
equals
(
stdout
))
{
builder
.
append
(
"\nSTDOUT:\n"
).
append
(
stdout
);
}
String
stderr
=
stderr
();
if
(!
""
.
equals
(
stderr
))
{
builder
.
append
(
"\nSTDERR:\n"
).
append
(
stderr
);
}
return
builder
.
toString
();
}
}
public
abstract
static
class
Matcher
extends
TypeSafeMatcher
<
Result
>
{
private
final
String
description
;
private
Matcher
(
String
description
)
{
this
.
description
=
description
;
}
@Override
protected
void
describeMismatchSafely
(
Result
result
,
Description
description
)
{
description
.
appendText
(
result
.
toString
());
}
public
void
describeTo
(
Description
description
)
{
description
.
appendText
(
this
.
description
);
}
public
static
Matcher
hasNoStandardOutput
()
{
return
new
Matcher
(
"No standard output"
)
{
@Override
protected
boolean
matchesSafely
(
Result
result
)
{
return
""
.
equals
(
result
.
stdout
());
}
};
}
public
static
Matcher
hasNoErrorOutput
()
{
return
new
Matcher
(
"No error output"
)
{
@Override
protected
boolean
matchesSafely
(
Result
result
)
{
return
""
.
equals
(
result
.
stderr
());
}
};
}
public
static
Matcher
succeeded
()
{
return
new
Matcher
(
"Exited with 0 return code"
)
{
@Override
protected
boolean
matchesSafely
(
Result
result
)
{
return
result
.
result
==
0
;
}
};
}
public
static
Matcher
failedWith
(
final
long
expectedCode
)
{
return
new
Matcher
(
"Exited with "
+
expectedCode
+
" return code"
)
{
@Override
protected
boolean
matchesSafely
(
Result
result
)
{
return
result
.
result
==
expectedCode
;
}
};
}
}
}
}
}
test/src/test/java/hudson/cli/CreateViewCommandTest.java
0 → 100644
浏览文件 @
b96d227f
/*
* The MIT License
*
* Copyright 2013 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
* 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
static
hudson
.
cli
.
CLICommandInvoker
.
Matcher
.
failedWith
;
import
static
hudson
.
cli
.
CLICommandInvoker
.
Matcher
.
hasNoStandardOutput
;
import
static
hudson
.
cli
.
CLICommandInvoker
.
Matcher
.
hasNoErrorOutput
;
import
static
hudson
.
cli
.
CLICommandInvoker
.
Matcher
.
succeeded
;
import
static
org
.
hamcrest
.
MatcherAssert
.
assertThat
;
import
static
org
.
hamcrest
.
Matchers
.
containsString
;
import
static
org
.
hamcrest
.
Matchers
.
equalTo
;
import
static
org
.
hamcrest
.
Matchers
.
nullValue
;
import
java.io.IOException
;
import
hudson.model.ListView
;
import
hudson.model.View
;
import
jenkins.model.Jenkins
;
import
org.junit.Before
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.jvnet.hudson.test.JenkinsRule
;
public
class
CreateViewCommandTest
{
private
CLICommandInvoker
command
;
@Rule
public
final
JenkinsRule
j
=
new
JenkinsRule
();
@Before
public
void
setUp
()
{
command
=
new
CLICommandInvoker
(
j
,
new
CreateViewCommand
());
}
@Test
public
void
createViewShouldFailWithoutViewCreatePermission
()
{
final
CLICommandInvoker
.
Result
result
=
command
.
authorizedTo
(
Jenkins
.
READ
)
.
withStdin
(
this
.
getClass
().
getResourceAsStream
(
"/hudson/cli/view.xml"
))
.
invoke
()
;
assertThat
(
result
,
failedWith
(-
1
));
assertThat
(
result
,
hasNoStandardOutput
());
assertThat
(
result
.
stderr
(),
containsString
(
"user is missing the View/Create permission"
));
}
@Test
public
void
createViewShouldSucceed
()
{
final
CLICommandInvoker
.
Result
result
=
command
.
authorizedTo
(
View
.
CREATE
,
Jenkins
.
READ
)
.
withStdin
(
this
.
getClass
().
getResourceAsStream
(
"/hudson/cli/view.xml"
))
.
invoke
()
;
assertThat
(
result
,
succeeded
());
assertThat
(
result
,
hasNoErrorOutput
());
assertThat
(
result
,
hasNoStandardOutput
());
final
View
updatedView
=
j
.
jenkins
.
getView
(
"ViewFromXML"
);
assertThat
(
updatedView
.
getViewName
(),
equalTo
(
"ViewFromXML"
));
assertThat
(
updatedView
.
isFilterExecutors
(),
equalTo
(
true
));
assertThat
(
updatedView
.
isFilterQueue
(),
equalTo
(
false
));
}
@Test
public
void
createViewSpecifyingNameExplicitlyShouldSucceed
()
{
final
CLICommandInvoker
.
Result
result
=
command
.
authorizedTo
(
View
.
CREATE
,
Jenkins
.
READ
)
.
withStdin
(
this
.
getClass
().
getResourceAsStream
(
"/hudson/cli/view.xml"
))
.
invokeWithArgs
(
"CustomViewName"
)
;
assertThat
(
result
,
succeeded
());
assertThat
(
result
,
hasNoErrorOutput
());
assertThat
(
result
,
hasNoStandardOutput
());
assertThat
(
"A view with original name should not exist"
,
j
.
jenkins
.
getView
(
"ViewFromXML"
),
nullValue
());
final
View
updatedView
=
j
.
jenkins
.
getView
(
"CustomViewName"
);
assertThat
(
updatedView
.
getViewName
(),
equalTo
(
"CustomViewName"
));
assertThat
(
updatedView
.
isFilterExecutors
(),
equalTo
(
true
));
assertThat
(
updatedView
.
isFilterQueue
(),
equalTo
(
false
));
}
@Test
public
void
createViewShouldFailIfViewAlreadyExists
()
throws
IOException
{
j
.
jenkins
.
addView
(
new
ListView
(
"ViewFromXML"
));
final
CLICommandInvoker
.
Result
result
=
command
.
authorizedTo
(
View
.
CREATE
,
Jenkins
.
READ
)
.
withStdin
(
this
.
getClass
().
getResourceAsStream
(
"/hudson/cli/view.xml"
))
.
invoke
()
;
assertThat
(
result
,
failedWith
(-
1
));
assertThat
(
result
,
hasNoStandardOutput
());
assertThat
(
result
.
stderr
(),
containsString
(
"View 'ViewFromXML' already exists"
));
}
@Test
public
void
createViewShouldFailUsingInvalidName
()
{
final
CLICommandInvoker
.
Result
result
=
command
.
authorizedTo
(
View
.
CREATE
,
Jenkins
.
READ
)
.
withStdin
(
this
.
getClass
().
getResourceAsStream
(
"/hudson/cli/view.xml"
))
.
invokeWithArgs
(
".."
)
;
assertThat
(
result
,
failedWith
(-
1
));
assertThat
(
result
,
hasNoStandardOutput
());
assertThat
(
result
.
stderr
(),
containsString
(
"Invalid view name"
));
}
}
test/src/test/java/hudson/cli/DeleteViewCommandTest.java
0 → 100644
浏览文件 @
b96d227f
/*
* The MIT License
*
* Copyright 2013 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
* 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
static
org
.
hamcrest
.
MatcherAssert
.
assertThat
;
import
static
org
.
hamcrest
.
Matchers
.
containsString
;
import
static
org
.
hamcrest
.
Matchers
.
nullValue
;
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
.
failedWith
;
import
java.io.IOException
;
import
hudson.model.ListView
;
import
hudson.model.View
;
import
jenkins.model.Jenkins
;
import
org.junit.Before
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.jvnet.hudson.test.JenkinsRule
;
public
class
DeleteViewCommandTest
{
private
CLICommandInvoker
command
;
@Rule
public
final
JenkinsRule
j
=
new
JenkinsRule
();
@Before
public
void
setUp
()
{
command
=
new
CLICommandInvoker
(
j
,
new
DeleteViewCommand
());
}
@Test
public
void
deleteViewShouldFailWithoutViewDeletePermission
()
throws
IOException
{
j
.
jenkins
.
addView
(
new
ListView
(
"aView"
));
final
CLICommandInvoker
.
Result
result
=
command
.
authorizedTo
(
View
.
READ
,
Jenkins
.
READ
)
.
invokeWithArgs
(
"aView"
)
;
assertThat
(
result
,
failedWith
(-
1
));
assertThat
(
result
,
hasNoStandardOutput
());
assertThat
(
result
.
stderr
(),
containsString
(
"user is missing the View/Delete permission"
));
}
@Test
public
void
deleteViewShouldSucceed
()
throws
Exception
{
j
.
jenkins
.
addView
(
new
ListView
(
"aView"
));
final
CLICommandInvoker
.
Result
result
=
command
.
authorizedTo
(
View
.
READ
,
View
.
DELETE
,
Jenkins
.
READ
)
.
invokeWithArgs
(
"aView"
)
;
assertThat
(
result
,
succeeded
());
assertThat
(
result
,
hasNoStandardOutput
());
assertThat
(
result
,
hasNoErrorOutput
());
assertThat
(
j
.
jenkins
.
getView
(
"aView"
),
nullValue
());
}
@Test
public
void
deleteViewShouldFailIfViewDoesNotExist
()
{
final
CLICommandInvoker
.
Result
result
=
command
.
authorizedTo
(
View
.
READ
,
View
.
DELETE
,
Jenkins
.
READ
)
.
invokeWithArgs
(
"never_created"
)
;
assertThat
(
result
,
failedWith
(-
1
));
assertThat
(
result
,
hasNoStandardOutput
());
assertThat
(
result
.
stderr
(),
containsString
(
"No view named never_created inside view Jenkins"
));
}
// ViewGroup.canDelete()
@Test
public
void
deleteViewShouldFailIfViewGroupDoesNotAllowDeletion
()
{
final
CLICommandInvoker
.
Result
result
=
command
.
authorizedTo
(
View
.
READ
,
View
.
DELETE
,
Jenkins
.
READ
)
.
invokeWithArgs
(
"All"
)
;
assertThat
(
result
,
failedWith
(-
1
));
assertThat
(
result
,
hasNoStandardOutput
());
assertThat
(
result
.
stderr
(),
containsString
(
"Jenkins does not allow to delete 'All' view"
));
}
}
test/src/test/java/hudson/cli/GetViewCommandTest.java
0 → 100644
浏览文件 @
b96d227f
/*
* The MIT License
*
* Copyright 2013 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
* 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
static
org
.
hamcrest
.
MatcherAssert
.
assertThat
;
import
static
org
.
hamcrest
.
Matchers
.
containsString
;
import
static
org
.
hamcrest
.
Matchers
.
startsWith
;
import
static
hudson
.
cli
.
CLICommandInvoker
.
Matcher
.
failedWith
;
import
static
hudson
.
cli
.
CLICommandInvoker
.
Matcher
.
hasNoStandardOutput
;
import
static
hudson
.
cli
.
CLICommandInvoker
.
Matcher
.
hasNoErrorOutput
;
import
static
hudson
.
cli
.
CLICommandInvoker
.
Matcher
.
succeeded
;
import
java.io.IOException
;
import
hudson.model.ListView
;
import
hudson.model.View
;
import
jenkins.model.Jenkins
;
import
org.junit.Before
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.jvnet.hudson.test.JenkinsRule
;
public
class
GetViewCommandTest
{
private
CLICommandInvoker
command
;
@Rule
public
final
JenkinsRule
j
=
new
JenkinsRule
();
@Before
public
void
setUp
()
{
command
=
new
CLICommandInvoker
(
j
,
new
GetViewCommand
());
}
@Test
public
void
getViewShouldFailWithoutViewReadPermission
()
throws
IOException
{
j
.
jenkins
.
addView
(
new
ListView
(
"aView"
));
final
CLICommandInvoker
.
Result
result
=
command
.
authorizedTo
(
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
getViewShouldYieldConfigXml
()
throws
Exception
{
j
.
jenkins
.
addView
(
new
ListView
(
"aView"
));
final
CLICommandInvoker
.
Result
result
=
command
.
authorizedTo
(
View
.
READ
,
Jenkins
.
READ
)
.
invokeWithArgs
(
"aView"
)
;
assertThat
(
result
,
succeeded
());
assertThat
(
result
,
hasNoErrorOutput
());
assertThat
(
result
.
stdout
(),
startsWith
(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
));
assertThat
(
result
.
stdout
(),
containsString
(
"<name>aView</name>"
));
}
@Test
public
void
getViewShouldFailIfViewDoesNotExist
()
{
final
CLICommandInvoker
.
Result
result
=
command
.
authorizedTo
(
View
.
READ
,
Jenkins
.
READ
)
.
invokeWithArgs
(
"never_created"
)
;
assertThat
(
result
,
failedWith
(-
1
));
assertThat
(
result
,
hasNoStandardOutput
());
assertThat
(
result
.
stderr
(),
containsString
(
"No view named never_created inside view Jenkins"
));
}
}
test/src/test/java/hudson/cli/UpdateViewCommandTest.java
0 → 100644
浏览文件 @
b96d227f
/*
* The MIT License
*
* Copyright 2013 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
* 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
static
hudson
.
cli
.
CLICommandInvoker
.
Matcher
.
failedWith
;
import
static
hudson
.
cli
.
CLICommandInvoker
.
Matcher
.
hasNoStandardOutput
;
import
static
hudson
.
cli
.
CLICommandInvoker
.
Matcher
.
hasNoErrorOutput
;
import
static
hudson
.
cli
.
CLICommandInvoker
.
Matcher
.
succeeded
;
import
static
org
.
hamcrest
.
MatcherAssert
.
assertThat
;
import
static
org
.
hamcrest
.
Matchers
.
containsString
;
import
static
org
.
hamcrest
.
Matchers
.
equalTo
;
import
static
org
.
hamcrest
.
Matchers
.
nullValue
;
import
hudson.model.ListView
;
import
hudson.model.View
;
import
jenkins.model.Jenkins
;
import
org.junit.Before
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.jvnet.hudson.test.JenkinsRule
;
public
class
UpdateViewCommandTest
{
private
CLICommandInvoker
command
;
@Rule
public
final
JenkinsRule
j
=
new
JenkinsRule
();
@Before
public
void
setUp
()
{
command
=
new
CLICommandInvoker
(
j
,
new
UpdateViewCommand
());
}
@Test
public
void
updateViewShouldFailWithoutViewConfigurePermission
()
throws
Exception
{
j
.
jenkins
.
addView
(
new
ListView
(
"aView"
));
final
CLICommandInvoker
.
Result
result
=
command
.
authorizedTo
(
View
.
READ
,
Jenkins
.
READ
)
.
withStdin
(
this
.
getClass
().
getResourceAsStream
(
"/hudson/cli/view.xml"
))
.
invokeWithArgs
(
"aView"
)
;
assertThat
(
result
,
failedWith
(-
1
));
assertThat
(
result
,
hasNoStandardOutput
());
assertThat
(
result
.
stderr
(),
containsString
(
"user is missing the View/Configure permission"
));
}
@Test
public
void
updateViewShouldModifyViewConfiguration
()
throws
Exception
{
j
.
jenkins
.
addView
(
new
ListView
(
"aView"
));
final
CLICommandInvoker
.
Result
result
=
command
.
authorizedTo
(
View
.
READ
,
View
.
CONFIGURE
,
Jenkins
.
READ
)
.
withStdin
(
this
.
getClass
().
getResourceAsStream
(
"/hudson/cli/view.xml"
))
.
invokeWithArgs
(
"aView"
)
;
assertThat
(
result
,
succeeded
());
assertThat
(
result
,
hasNoErrorOutput
());
assertThat
(
"Update should not modify view name"
,
j
.
jenkins
.
getView
(
"ViewFromXML"
),
nullValue
());
final
View
updatedView
=
j
.
jenkins
.
getView
(
"aView"
);
assertThat
(
updatedView
.
getViewName
(),
equalTo
(
"aView"
));
assertThat
(
updatedView
.
isFilterExecutors
(),
equalTo
(
true
));
assertThat
(
updatedView
.
isFilterQueue
(),
equalTo
(
false
));
}
@Test
public
void
updateViewShouldFailIfViewDoesNotExist
()
{
final
CLICommandInvoker
.
Result
result
=
command
.
authorizedTo
(
View
.
READ
,
View
.
CONFIGURE
,
Jenkins
.
READ
)
.
withStdin
(
this
.
getClass
().
getResourceAsStream
(
"/hudson/cli/view.xml"
))
.
invokeWithArgs
(
"not_created"
)
;
assertThat
(
result
,
failedWith
(-
1
));
assertThat
(
result
,
hasNoStandardOutput
());
assertThat
(
result
.
stderr
(),
containsString
(
"No view named not_created inside view Jenkins"
));
}
}
test/src/test/resources/hudson/cli/view.xml
0 → 100644
浏览文件 @
b96d227f
<?xml version="1.0" encoding="UTF-8"?>
<hudson.model.ListView>
<name>
ViewFromXML
</name>
<filterExecutors>
true
</filterExecutors>
<filterQueue>
false
</filterQueue>
<properties
class=
"hudson.model.View$PropertyList"
/>
<jobNames>
<comparator
class=
"hudson.util.CaseInsensitiveComparator"
/>
<string>
core_selenium-test
</string>
<string>
jenkins_lts_branch
</string>
<string>
jenkins_main_maven-3.1.0
</string>
<string>
jenkins_main_trunk
</string>
<string>
jenkins_pom
</string>
<string>
jenkins_rc_branch
</string>
<string>
jenkins_ui-changes_branch
</string>
<string>
remoting
</string>
<string>
selenium-tests
</string>
</jobNames>
<jobFilters/>
<columns>
<hudson.views.StatusColumn/>
<hudson.views.WeatherColumn/>
<hudson.views.JobColumn/>
<hudson.views.LastSuccessColumn/>
<hudson.views.LastFailureColumn/>
<hudson.views.LastDurationColumn/>
<org.jenkins.ci.plugins.column.console.LastBuildColumn
plugin=
"console-column-plugin@1.5"
/>
<hudson.views.BuildButtonColumn/>
</columns>
<recurse>
false
</recurse>
</hudson.model.ListView>
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录