Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
LinuxSuRen
jenkins
提交
f39c6b7b
J
jenkins
项目概览
LinuxSuRen
/
jenkins
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
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,发现更多精彩内容 >>
提交
f39c6b7b
编写于
12月 20, 2016
作者:
J
Jesse Glick
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'security-stable-2.7' into security-stable-2.19
上级
47530913
2cdabc1d
变更
17
展开全部
隐藏空白更改
内联
并排
Showing
17 changed file
with
958 addition
and
27 deletion
+958
-27
core/pom.xml
core/pom.xml
+0
-6
core/src/main/java/hudson/diagnosis/HudsonHomeDiskUsageMonitor.java
...ain/java/hudson/diagnosis/HudsonHomeDiskUsageMonitor.java
+2
-0
core/src/main/java/hudson/diagnosis/OldDataMonitor.java
core/src/main/java/hudson/diagnosis/OldDataMonitor.java
+1
-0
core/src/main/java/hudson/diagnosis/ReverseProxySetupMonitor.java
.../main/java/hudson/diagnosis/ReverseProxySetupMonitor.java
+2
-0
core/src/main/java/hudson/diagnosis/TooManyJobsButNoView.java
.../src/main/java/hudson/diagnosis/TooManyJobsButNoView.java
+2
-0
core/src/main/java/hudson/model/AdministrativeMonitor.java
core/src/main/java/hudson/model/AdministrativeMonitor.java
+15
-2
core/src/main/java/hudson/security/BCrypt.java
core/src/main/java/hudson/security/BCrypt.java
+777
-0
core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java
...main/java/hudson/security/HudsonPrivateSecurityRealm.java
+0
-1
core/src/main/java/jenkins/diagnostics/SecurityIsOffMonitor.java
...c/main/java/jenkins/diagnostics/SecurityIsOffMonitor.java
+2
-0
core/src/main/java/jenkins/model/Jenkins.java
core/src/main/java/jenkins/model/Jenkins.java
+0
-6
core/src/main/java/jenkins/security/RekeySecretAdminMonitor.java
...c/main/java/jenkins/security/RekeySecretAdminMonitor.java
+1
-10
core/src/main/java/jenkins/security/s2m/AdminCallableMonitor.java
.../main/java/jenkins/security/s2m/AdminCallableMonitor.java
+2
-0
core/src/main/java/jenkins/security/s2m/MasterKillSwitchWarning.java
...in/java/jenkins/security/s2m/MasterKillSwitchWarning.java
+2
-0
core/src/main/resources/hudson/diagnosis/HudsonHomeDiskUsageMonitor/index.jelly
...s/hudson/diagnosis/HudsonHomeDiskUsageMonitor/index.jelly
+1
-1
core/src/main/resources/hudson/diagnosis/OldDataMonitor/manage.jelly
...in/resources/hudson/diagnosis/OldDataMonitor/manage.jelly
+1
-1
test/src/test/java/hudson/diagnosis/HudsonHomeDiskUsageMonitorTest.java
...java/hudson/diagnosis/HudsonHomeDiskUsageMonitorTest.java
+55
-0
test/src/test/java/jenkins/security/Security380Test.java
test/src/test/java/jenkins/security/Security380Test.java
+95
-0
未找到文件。
core/pom.xml
浏览文件 @
f39c6b7b
...
...
@@ -591,12 +591,6 @@ THE SOFTWARE.
<version>
1.3.1-jenkins-1
</version>
</dependency>
<dependency>
<groupId>
org.mindrot
</groupId>
<artifactId>
jbcrypt
</artifactId>
<version>
0.3m
</version>
</dependency>
<!-- offline profiler API to put in the classpath if we need it -->
<!--dependency>
<groupId>com.yourkit.api</groupId>
...
...
core/src/main/java/hudson/diagnosis/HudsonHomeDiskUsageMonitor.java
浏览文件 @
f39c6b7b
...
...
@@ -32,6 +32,7 @@ import org.jenkinsci.Symbol;
import
org.kohsuke.stapler.HttpResponse
;
import
org.kohsuke.stapler.HttpResponses
;
import
org.kohsuke.stapler.QueryParameter
;
import
org.kohsuke.stapler.interceptor.RequirePOST
;
import
java.io.IOException
;
import
java.util.List
;
...
...
@@ -64,6 +65,7 @@ public final class HudsonHomeDiskUsageMonitor extends AdministrativeMonitor {
/**
* Depending on whether the user said "yes" or "no", send him to the right place.
*/
@RequirePOST
public
HttpResponse
doAct
(
@QueryParameter
String
no
)
throws
IOException
{
if
(
no
!=
null
)
{
disable
(
true
);
...
...
core/src/main/java/hudson/diagnosis/OldDataMonitor.java
浏览文件 @
f39c6b7b
...
...
@@ -52,6 +52,7 @@ import java.util.concurrent.ConcurrentMap;
import
java.util.logging.Level
;
import
java.util.logging.Logger
;
import
javax.annotation.CheckForNull
;
import
jenkins.model.Jenkins
;
import
org.acegisecurity.context.SecurityContext
;
import
org.acegisecurity.context.SecurityContextHolder
;
...
...
core/src/main/java/hudson/diagnosis/ReverseProxySetupMonitor.java
浏览文件 @
f39c6b7b
...
...
@@ -37,6 +37,7 @@ import java.util.logging.Level;
import
java.util.logging.Logger
;
import
jenkins.model.Jenkins
;
import
org.kohsuke.stapler.Stapler
;
import
org.kohsuke.stapler.interceptor.RequirePOST
;
/**
* Looks out for a broken reverse proxy setup that doesn't rewrite the location header correctly.
...
...
@@ -84,6 +85,7 @@ public class ReverseProxySetupMonitor extends AdministrativeMonitor {
/**
* Depending on whether the user said "yes" or "no", send him to the right place.
*/
@RequirePOST
public
HttpResponse
doAct
(
@QueryParameter
String
no
)
throws
IOException
{
if
(
no
!=
null
)
{
// dismiss
disable
(
true
);
...
...
core/src/main/java/hudson/diagnosis/TooManyJobsButNoView.java
浏览文件 @
f39c6b7b
...
...
@@ -29,6 +29,7 @@ import hudson.Extension;
import
org.jenkinsci.Symbol
;
import
org.kohsuke.stapler.StaplerRequest
;
import
org.kohsuke.stapler.StaplerResponse
;
import
org.kohsuke.stapler.interceptor.RequirePOST
;
import
java.io.IOException
;
...
...
@@ -50,6 +51,7 @@ public class TooManyJobsButNoView extends AdministrativeMonitor {
/**
* Depending on whether the user said "yes" or "no", send him to the right place.
*/
@RequirePOST
public
void
doAct
(
StaplerRequest
req
,
StaplerResponse
rsp
)
throws
IOException
{
if
(
req
.
hasParameter
(
"no"
))
{
disable
(
true
);
...
...
core/src/main/java/hudson/model/AdministrativeMonitor.java
浏览文件 @
f39c6b7b
...
...
@@ -33,8 +33,12 @@ import java.util.Set;
import
java.io.IOException
;
import
jenkins.model.Jenkins
;
import
org.kohsuke.accmod.Restricted
;
import
org.kohsuke.accmod.restrictions.NoExternalUse
;
import
org.kohsuke.stapler.StaplerProxy
;
import
org.kohsuke.stapler.StaplerRequest
;
import
org.kohsuke.stapler.StaplerResponse
;
import
org.kohsuke.stapler.interceptor.RequirePOST
;
/**
* Checks the health of a subsystem of Jenkins and if there's something
...
...
@@ -74,7 +78,7 @@ import org.kohsuke.stapler.StaplerResponse;
* @see Jenkins#administrativeMonitors
*/
@LegacyInstancesAreScopedToHudson
public
abstract
class
AdministrativeMonitor
extends
AbstractModelObject
implements
ExtensionPoint
{
public
abstract
class
AdministrativeMonitor
extends
AbstractModelObject
implements
ExtensionPoint
,
StaplerProxy
{
/**
* Human-readable ID of this monitor, which needs to be unique within the system.
*
...
...
@@ -142,12 +146,21 @@ public abstract class AdministrativeMonitor extends AbstractModelObject implemen
/**
* URL binding to disable this monitor.
*/
@RequirePOST
public
void
doDisable
(
StaplerRequest
req
,
StaplerResponse
rsp
)
throws
IOException
{
Jenkins
.
getInstance
().
checkPermission
(
Jenkins
.
ADMINISTER
);
disable
(
true
);
rsp
.
sendRedirect2
(
req
.
getContextPath
()+
"/manage"
);
}
/**
* Requires ADMINISTER permission for any operation in here.
*/
@Restricted
(
NoExternalUse
.
class
)
public
Object
getTarget
()
{
Jenkins
.
getInstance
().
checkPermission
(
Jenkins
.
ADMINISTER
);
return
this
;
}
/**
* All registered {@link AdministrativeMonitor} instances.
*/
...
...
core/src/main/java/hudson/security/BCrypt.java
0 → 100644
浏览文件 @
f39c6b7b
此差异已折叠。
点击以展开。
core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java
浏览文件 @
f39c6b7b
...
...
@@ -60,7 +60,6 @@ import org.kohsuke.stapler.HttpResponses;
import
org.kohsuke.stapler.Stapler
;
import
org.kohsuke.stapler.StaplerRequest
;
import
org.kohsuke.stapler.StaplerResponse
;
import
org.mindrot.jbcrypt.BCrypt
;
import
org.springframework.dao.DataAccessException
;
import
javax.servlet.Filter
;
...
...
core/src/main/java/jenkins/diagnostics/SecurityIsOffMonitor.java
浏览文件 @
f39c6b7b
...
...
@@ -6,6 +6,7 @@ import jenkins.model.Jenkins;
import
org.jenkinsci.Symbol
;
import
org.kohsuke.stapler.StaplerRequest
;
import
org.kohsuke.stapler.StaplerResponse
;
import
org.kohsuke.stapler.interceptor.RequirePOST
;
import
java.io.IOException
;
...
...
@@ -28,6 +29,7 @@ public class SecurityIsOffMonitor extends AdministrativeMonitor {
/**
* Depending on whether the user said "yes" or "no", send him to the right place.
*/
@RequirePOST
public
void
doAct
(
StaplerRequest
req
,
StaplerResponse
rsp
)
throws
IOException
{
if
(
req
.
hasParameter
(
"no"
))
{
disable
(
true
);
...
...
core/src/main/java/jenkins/model/Jenkins.java
浏览文件 @
f39c6b7b
...
...
@@ -138,7 +138,6 @@ import hudson.security.AccessControlled;
import
hudson.security.AuthorizationStrategy
;
import
hudson.security.BasicAuthenticationFilter
;
import
hudson.security.FederatedLoginService
;
import
hudson.security.FullControlOnceLoggedInAuthorizationStrategy
;
import
hudson.security.HudsonFilter
;
import
hudson.security.LegacyAuthorizationStrategy
;
import
hudson.security.LegacySecurityRealm
;
...
...
@@ -1705,11 +1704,6 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve
*/
@Exported
(
name
=
"jobs"
)
public
List
<
TopLevelItem
>
getItems
()
{
if
(
authorizationStrategy
instanceof
AuthorizationStrategy
.
Unsecured
||
authorizationStrategy
instanceof
FullControlOnceLoggedInAuthorizationStrategy
)
{
return
new
ArrayList
(
items
.
values
());
}
List
<
TopLevelItem
>
viewableItems
=
new
ArrayList
<
TopLevelItem
>();
for
(
TopLevelItem
item
:
items
.
values
())
{
if
(
item
.
hasPermission
(
Item
.
READ
))
...
...
core/src/main/java/jenkins/security/RekeySecretAdminMonitor.java
浏览文件 @
f39c6b7b
...
...
@@ -12,7 +12,6 @@ import jenkins.model.Jenkins;
import
jenkins.util.io.FileBoolean
;
import
org.jenkinsci.Symbol
;
import
org.kohsuke.stapler.HttpResponse
;
import
org.kohsuke.stapler.StaplerProxy
;
import
org.kohsuke.stapler.StaplerRequest
;
import
org.kohsuke.stapler.interceptor.RequirePOST
;
...
...
@@ -30,7 +29,7 @@ import java.util.logging.Logger;
* @author Kohsuke Kawaguchi
*/
@Extension
@Symbol
(
"rekeySecret"
)
public
class
RekeySecretAdminMonitor
extends
AsynchronousAdministrativeMonitor
implements
StaplerProxy
{
public
class
RekeySecretAdminMonitor
extends
AsynchronousAdministrativeMonitor
{
/**
* Whether we detected a need to run the rewrite program.
...
...
@@ -63,14 +62,6 @@ public class RekeySecretAdminMonitor extends AsynchronousAdministrativeMonitor i
needed
.
on
();
}
/**
* Requires ADMINISTER permission for any operation in here.
*/
public
Object
getTarget
()
{
Jenkins
.
getInstance
().
checkPermission
(
Jenkins
.
ADMINISTER
);
return
this
;
}
@Override
public
boolean
isActivated
()
{
return
needed
.
isOn
();
...
...
core/src/main/java/jenkins/security/s2m/AdminCallableMonitor.java
浏览文件 @
f39c6b7b
...
...
@@ -9,6 +9,7 @@ import org.jenkinsci.Symbol;
import
org.kohsuke.stapler.HttpResponse
;
import
org.kohsuke.stapler.HttpResponses
;
import
org.kohsuke.stapler.QueryParameter
;
import
org.kohsuke.stapler.interceptor.RequirePOST
;
import
javax.inject.Inject
;
import
java.io.IOException
;
...
...
@@ -50,6 +51,7 @@ public class AdminCallableMonitor extends AdministrativeMonitor {
/**
* Depending on whether the user said "examin" or "dismiss", send him to the right place.
*/
@RequirePOST
public
HttpResponse
doAct
(
@QueryParameter
String
dismiss
)
throws
IOException
{
if
(
dismiss
!=
null
)
{
disable
(
true
);
...
...
core/src/main/java/jenkins/security/s2m/MasterKillSwitchWarning.java
浏览文件 @
f39c6b7b
...
...
@@ -5,6 +5,7 @@ import hudson.model.AdministrativeMonitor;
import
org.kohsuke.stapler.HttpResponse
;
import
org.kohsuke.stapler.HttpResponses
;
import
org.kohsuke.stapler.QueryParameter
;
import
org.kohsuke.stapler.interceptor.RequirePOST
;
import
javax.inject.Inject
;
import
java.io.IOException
;
...
...
@@ -28,6 +29,7 @@ public class MasterKillSwitchWarning extends AdministrativeMonitor {
return
rule
.
getMasterKillSwitch
()
&&
config
.
isRelevant
();
}
@RequirePOST
public
HttpResponse
doAct
(
@QueryParameter
String
dismiss
)
throws
IOException
{
if
(
dismiss
!=
null
)
{
disable
(
true
);
...
...
core/src/main/resources/hudson/diagnosis/HudsonHomeDiskUsageMonitor/index.jelly
浏览文件 @
f39c6b7b
...
...
@@ -24,7 +24,7 @@ THE SOFTWARE.
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
<l:layout title="${%JENKINS_HOME is almost full}"
permission="${app.ADMINISTER}"
>
<l:layout title="${%JENKINS_HOME is almost full}">
<l:main-panel>
<h1>
<l:icon class="icon-warning icon-xlg"/>
...
...
core/src/main/resources/hudson/diagnosis/OldDataMonitor/manage.jelly
浏览文件 @
f39c6b7b
...
...
@@ -24,7 +24,7 @@ THE SOFTWARE.
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<l:layout title="${%Manage Old Data}"
permission="${app.ADMINISTER}"
>
<l:layout title="${%Manage Old Data}">
<st:include page="sidepanel.jelly" it="${app}"/>
<l:main-panel>
<h1>${%Manage Old Data}</h1>
...
...
test/src/test/java/hudson/diagnosis/HudsonHomeDiskUsageMonitorTest.java
浏览文件 @
f39c6b7b
package
hudson.diagnosis
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertFalse
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
junit
.
Assert
.
fail
;
import
com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException
;
import
com.gargoylesoftware.htmlunit.HttpMethod
;
import
com.gargoylesoftware.htmlunit.WebRequest
;
import
com.gargoylesoftware.htmlunit.util.NameValuePair
;
import
hudson.model.User
;
import
hudson.security.GlobalMatrixAuthorizationStrategy
;
import
hudson.security.HudsonPrivateSecurityRealm
;
import
hudson.security.Permission
;
import
jenkins.model.Jenkins
;
import
org.acegisecurity.context.SecurityContextHolder
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.jvnet.hudson.test.Issue
;
import
org.jvnet.hudson.test.JenkinsRule
;
import
org.xml.sax.SAXException
;
import
com.gargoylesoftware.htmlunit.html.HtmlPage
;
...
...
@@ -13,6 +25,7 @@ import com.gargoylesoftware.htmlunit.html.HtmlForm;
import
com.gargoylesoftware.htmlunit.ElementNotFoundException
;
import
java.io.IOException
;
import
java.util.Collections
;
/**
* @author Kohsuke Kawaguchi
...
...
@@ -45,6 +58,48 @@ public class HudsonHomeDiskUsageMonitorTest {
}
}
@Issue
(
"SECURITY-371"
)
@Test
public
void
noAccessForNonAdmin
()
throws
Exception
{
JenkinsRule
.
WebClient
wc
=
j
.
createWebClient
();
// TODO: Use MockAuthorizationStrategy in later versions
JenkinsRule
.
DummySecurityRealm
realm
=
j
.
createDummySecurityRealm
();
realm
.
addGroups
(
"administrator"
,
"admins"
);
realm
.
addGroups
(
"bob"
,
"users"
);
j
.
jenkins
.
setSecurityRealm
(
realm
);
GlobalMatrixAuthorizationStrategy
auth
=
new
GlobalMatrixAuthorizationStrategy
();
auth
.
add
(
Jenkins
.
ADMINISTER
,
"admins"
);
auth
.
add
(
Jenkins
.
READ
,
"users"
);
j
.
jenkins
.
setAuthorizationStrategy
(
auth
);
WebRequest
request
=
new
WebRequest
(
wc
.
createCrumbedUrl
(
"administrativeMonitor/hudsonHomeIsFull/act"
),
HttpMethod
.
POST
);
NameValuePair
param
=
new
NameValuePair
(
"no"
,
"true"
);
request
.
setRequestParameters
(
Collections
.
singletonList
(
param
));
HudsonHomeDiskUsageMonitor
mon
=
HudsonHomeDiskUsageMonitor
.
get
();
try
{
wc
.
login
(
"bob"
);
wc
.
getPage
(
request
);
}
catch
(
FailingHttpStatusCodeException
e
)
{
assertEquals
(
403
,
e
.
getStatusCode
());
}
assertTrue
(
mon
.
isEnabled
());
try
{
WebRequest
getIndex
=
new
WebRequest
(
wc
.
createCrumbedUrl
(
"administrativeMonitor/hudsonHomeIsFull"
),
HttpMethod
.
GET
);
wc
.
getPage
(
getIndex
);
}
catch
(
FailingHttpStatusCodeException
e
)
{
assertEquals
(
403
,
e
.
getStatusCode
());
}
wc
.
login
(
"administrator"
);
wc
.
getPage
(
request
);
assertFalse
(
mon
.
isEnabled
());
}
/**
* Gets the warning form.
*/
...
...
test/src/test/java/jenkins/security/Security380Test.java
0 → 100644
浏览文件 @
f39c6b7b
package
jenkins.security
;
import
com.gargoylesoftware.htmlunit.Page
;
import
hudson.model.UnprotectedRootAction
;
import
hudson.security.ACL
;
import
hudson.security.FullControlOnceLoggedInAuthorizationStrategy
;
import
hudson.util.HttpResponses
;
import
jenkins.model.Jenkins
;
import
org.junit.Assert
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.jvnet.hudson.test.Issue
;
import
org.jvnet.hudson.test.JenkinsRule
;
import
org.jvnet.hudson.test.TestExtension
;
import
org.kohsuke.stapler.HttpResponse
;
public
class
Security380Test
{
@Rule
public
JenkinsRule
j
=
new
JenkinsRule
();
@Issue
(
"SECURITY-380"
)
@Test
public
void
testGetItemsWithoutAnonRead
()
throws
Exception
{
FullControlOnceLoggedInAuthorizationStrategy
strategy
=
new
FullControlOnceLoggedInAuthorizationStrategy
();
strategy
.
setAllowAnonymousRead
(
false
);
Jenkins
.
getInstance
().
setAuthorizationStrategy
(
strategy
);
Jenkins
.
getInstance
().
setSecurityRealm
(
j
.
createDummySecurityRealm
());
j
.
createFreeStyleProject
();
ACL
.
impersonate
(
Jenkins
.
ANONYMOUS
,
new
Runnable
()
{
@Override
public
void
run
()
{
Assert
.
assertEquals
(
"no items"
,
0
,
Jenkins
.
getInstance
().
getItems
().
size
());
}
});
}
@Issue
(
"SECURITY-380"
)
@Test
public
void
testGetItems
()
throws
Exception
{
FullControlOnceLoggedInAuthorizationStrategy
strategy
=
new
FullControlOnceLoggedInAuthorizationStrategy
();
strategy
.
setAllowAnonymousRead
(
true
);
Jenkins
.
getInstance
().
setAuthorizationStrategy
(
strategy
);
Jenkins
.
getInstance
().
setSecurityRealm
(
j
.
createDummySecurityRealm
());
j
.
createFreeStyleProject
();
ACL
.
impersonate
(
Jenkins
.
ANONYMOUS
,
new
Runnable
()
{
@Override
public
void
run
()
{
Assert
.
assertEquals
(
"one item"
,
1
,
Jenkins
.
getInstance
().
getItems
().
size
());
}
});
}
@Issue
(
"SECURITY-380"
)
@Test
public
void
testWithUnprotectedRootAction
()
throws
Exception
{
FullControlOnceLoggedInAuthorizationStrategy
strategy
=
new
FullControlOnceLoggedInAuthorizationStrategy
();
strategy
.
setAllowAnonymousRead
(
false
);
Jenkins
.
getInstance
().
setAuthorizationStrategy
(
strategy
);
Jenkins
.
getInstance
().
setSecurityRealm
(
j
.
createDummySecurityRealm
());
j
.
createFreeStyleProject
();
JenkinsRule
.
WebClient
wc
=
j
.
createWebClient
();
Page
page
=
wc
.
goTo
(
"listJobs"
,
"text/plain"
);
Assert
.
assertEquals
(
"expect 0 items"
,
"0"
,
page
.
getWebResponse
().
getContentAsString
().
trim
());
}
@TestExtension
public
static
class
JobListingUnprotectedRootAction
implements
UnprotectedRootAction
{
@Override
public
String
getIconFileName
()
{
return
null
;
}
@Override
public
String
getDisplayName
()
{
return
null
;
}
@Override
public
String
getUrlName
()
{
return
"listJobs"
;
}
public
HttpResponse
doIndex
()
throws
Exception
{
return
HttpResponses
.
plainText
(
Integer
.
toString
(
Jenkins
.
getInstance
().
getItems
().
size
()));
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录