Skip to content

Commit 8e53498

Browse files
janfaraciktimja
andauthored
Adjust for experimental Manage Jenkins UI (#2756)
Co-authored-by: Tim Jacomb <[email protected]> Co-authored-by: Tim Jacomb <[email protected]>
1 parent 0bc2de7 commit 8e53498

10 files changed

Lines changed: 170 additions & 98 deletions

File tree

integrations/pom.xml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
<properties>
1414
<!-- no need to be deployed during release, this is a test-only module -->
1515
<maven.deploy.skip>true</maven.deploy.skip>
16-
<jenkins.baseline>2.516</jenkins.baseline>
17-
<jenkins.version>${jenkins.baseline}.3</jenkins.version>
1816
</properties>
1917

2018
<dependencyManagement>

plugin/src/main/java/io/jenkins/plugins/casc/ConfigurationAsCode.java

Lines changed: 58 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ public String getUrlName() {
140140

141141
@Override
142142
public String getDescription() {
143-
return "Reload your configuration or update configuration source";
143+
return "Reload your configuration or update configuration source.";
144144
}
145145

146146
/**
@@ -218,38 +218,51 @@ public void doReplace(StaplerRequest2 request, StaplerResponse2 response) throws
218218
response.sendError(HttpServletResponse.SC_FORBIDDEN);
219219
return;
220220
}
221-
String newSource = request.getParameter("_.newSource");
222-
String normalizedSource = Util.fixEmptyAndTrim(newSource);
223-
List<String> candidateSources = new ArrayList<>();
224-
for (String candidateSource : inputToCandidateSources(normalizedSource)) {
225-
File file = new File(candidateSource);
226-
if (file.exists() || ConfigurationAsCode.isSupportedURI(candidateSource)) {
227-
candidateSources.add(candidateSource);
228-
} else {
229-
LOGGER.log(Level.WARNING, "Source {0} could not be applied", candidateSource);
230-
// todo: show message in UI
221+
try {
222+
String newSource = request.getParameter("_.newSource");
223+
String normalizedSource = Util.fixEmptyAndTrim(newSource);
224+
List<String> candidateSources = new ArrayList<>();
225+
for (String candidateSource : inputToCandidateSources(normalizedSource)) {
226+
File file = new File(candidateSource);
227+
if (file.exists() || ConfigurationAsCode.isSupportedURI(candidateSource)) {
228+
candidateSources.add(candidateSource);
229+
} else {
230+
LOGGER.log(Level.WARNING, "Source {0} could not be applied", candidateSource);
231+
// todo: show message in UI
232+
}
231233
}
232-
}
233-
if (!candidateSources.isEmpty()) {
234-
List<YamlSource> candidates = getConfigFromSources(candidateSources);
235-
if (canApplyFrom(candidates)) {
236-
sources = candidateSources;
237-
configureWith(getConfigFromSources(getSources()));
238-
CasCGlobalConfig config = GlobalConfiguration.all().get(CasCGlobalConfig.class);
239-
if (config != null) {
240-
config.setConfigurationPath(normalizedSource);
241-
config.save();
234+
if (!candidateSources.isEmpty()) {
235+
List<YamlSource> candidates = getConfigFromSources(candidateSources);
236+
if (canApplyFrom(candidates)) {
237+
sources = candidateSources;
238+
configureWith(getConfigFromSources(getSources()));
239+
CasCGlobalConfig config = GlobalConfiguration.all().get(CasCGlobalConfig.class);
240+
if (config != null) {
241+
config.setConfigurationPath(normalizedSource);
242+
config.save();
243+
}
244+
LOGGER.log(Level.FINE, "Replace configuration with: " + normalizedSource);
245+
} else {
246+
LOGGER.log(Level.WARNING, "Provided sources could not be applied");
247+
// todo: show message in UI
242248
}
243-
LOGGER.log(Level.FINE, "Replace configuration with: " + normalizedSource);
244249
} else {
245-
LOGGER.log(Level.WARNING, "Provided sources could not be applied");
246-
// todo: show message in UI
250+
LOGGER.log(Level.FINE, "No such source exists, applying default");
251+
// May be do nothing instead?
252+
configure();
247253
}
248-
} else {
249-
LOGGER.log(Level.FINE, "No such source exists, applying default");
250-
// May be do nothing instead?
251-
configure();
254+
} catch (ConfiguratorException e) {
255+
LOGGER.log(Level.SEVERE, "Failed to reload configuration", e);
256+
257+
Throwable throwableCause = e.getCause();
258+
if (throwableCause instanceof ConfiguratorException cause) {
259+
handleExceptionOnReloading(request, response, cause);
260+
} else {
261+
handleExceptionOnReloading(request, response, e);
262+
}
263+
return;
252264
}
265+
253266
response.sendRedirect("");
254267
}
255268

@@ -556,7 +569,23 @@ public void doViewExport(StaplerRequest2 req, StaplerResponse2 res) throws Excep
556569
ByteArrayOutputStream out = new ByteArrayOutputStream();
557570
export(out);
558571

559-
req.setAttribute("export", out.toString(StandardCharsets.UTF_8.name()));
572+
req.setAttribute("viewExport", new ManagementLink() {
573+
@Override
574+
public String getIconFileName() {
575+
return "";
576+
}
577+
578+
// TODO - FIX - EXTREMELY HACKY - couldn't expose a public method for some reason
579+
@Override
580+
public String getUrlName() {
581+
return out.toString(StandardCharsets.UTF_8);
582+
}
583+
584+
@Override
585+
public String getDisplayName() {
586+
return "Export configuration";
587+
}
588+
});
560589
req.getView(this, "viewExport.jelly").forward(req, res);
561590
}
562591

Lines changed: 74 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,93 @@
11
<?jelly escape-by-default='true'?>
2-
<j:jelly xmlns:j="jelly:core" xmlns:l="/lib/layout" xmlns:f="/lib/form" xmlns:i="jelly:fmt" xmlns:st="jelly:stapler">
3-
<l:layout type="one-column" title="${%Configuration as Code}" permissions="${app.MANAGE_AND_SYSTEM_READ}">
4-
<l:main-panel>
5-
<l:app-bar title="${%Configuration as Code}">
2+
<j:jelly xmlns:j="jelly:core" xmlns:l="/lib/layout" xmlns:f="/lib/form" xmlns:i="jelly:fmt"
3+
xmlns:t="/lib/hudson">
4+
<l:settings-subpage permissions="${app.MANAGE_AND_SYSTEM_READ}" header="${null}">
5+
<l:dialog title="${%Apply Configuration as Code file}" hash="new">
6+
<l:isAdmin>
7+
<f:form method="post" action="replace" name="replace">
8+
<input type="hidden" name="${h.getCrumbRequestField()}" value="${h.getCrumb(request2)}"/>
9+
<f:entry title="${%Path or URL}" field="newSource" class="jenkins-form-item--small">
10+
<f:textbox checkUrl="checkNewSource" checkDependsOn="newSource"/>
11+
</f:entry>
12+
<f:submit name="replace" value="${%Apply configuration}"/>
13+
</f:form>
14+
</l:isAdmin>
15+
</l:dialog>
16+
17+
<l:app-bar title="${it.displayName}">
18+
<j:if test="${!empty it.sources}">
19+
<button id="btn-open-apply-configuration" class="jenkins-button"
20+
data-type="dialog-opener"
21+
data-dialog-id="${dialogId}">
22+
<l:icon src="symbol-add"/>
23+
${%Apply configuration}
24+
</button>
25+
</j:if>
626

7-
<f:form method="post" action="reload" name="reload">
8-
<l:hasAdministerOrManage>
9-
<f:submit icon="symbol-refresh" primary="false" name="reload"
10-
value="${%Reload existing configuration}"/>
11-
</l:hasAdministerOrManage>
12-
</f:form>
1327
<f:form method="post" action="viewExport" name="viewExport">
1428
<l:hasPermission permission="${app.SYSTEM_READ}">
15-
<f:submit primary="false" name="viewExport" value="${%Export configuration}"/>
29+
<button name="viewExport" class="jenkins-button">
30+
${%Export configuration}
31+
</button>
1632
</l:hasPermission>
1733
</f:form>
34+
35+
<j:if test="${!empty it.sources}">
36+
<f:form method="post" action="reload" name="reload">
37+
<l:hasAdministerOrManage>
38+
<button name="reload" tooltip="${%Reload configuration}" class="jenkins-button">
39+
<l:icon src="symbol-refresh"/>
40+
</button>
41+
</l:hasAdministerOrManage>
42+
</f:form>
43+
</j:if>
1844
</l:app-bar>
1945

46+
<p class="jenkins-page-description">
47+
${it.description}
48+
</p>
49+
2050
<j:choose>
2151
<j:when test="${empty it.sources}">
22-
<p>${%Controller has no configuration as code file set.}</p>
52+
<l:notice icon="symbol-logo plugin-configuration-as-code"
53+
title="${%Controller has no configuration as code file set}">
54+
<l:isAdmin>
55+
<button id="btn-open-apply-configuration" class="jenkins-button"
56+
data-type="dialog-opener"
57+
data-dialog-id="${dialogId}">
58+
${%Setup configuration}
59+
</button>
60+
</l:isAdmin>
61+
</l:notice>
2362
</j:when>
2463
<j:otherwise>
25-
${%Configuration loaded from :}
26-
<ul>
27-
<j:forEach var="source" items="${it.sources}">
28-
<li>${source}</li>
29-
</j:forEach>
30-
</ul>
31-
32-
<p>${%Last time applied:} <i:formatDate value="${it.lastTimeLoaded}" type="both" dateStyle="medium" timeStyle="long"/></p>
64+
<f:section title="${%Configurations}">
65+
<p class="jenkins-section__description">
66+
${%Last time applied:}
67+
<i:formatDate value="${it.lastTimeLoaded}" type="both" dateStyle="medium"
68+
timeStyle="long"/>
69+
</p>
3370

71+
<ul class="jenkins-instructions">
72+
<j:forEach var="source" items="${it.sources}">
73+
<li style="font-family: var(--font-family-mono)">${source}</li>
74+
</j:forEach>
75+
</ul>
76+
</f:section>
3477
</j:otherwise>
3578
</j:choose>
3679

37-
<l:isAdmin>
38-
<f:form method="post" action="replace" name="replace">
39-
<h2>${%Replace configuration source with:}</h2>
40-
<f:entry title="${%Path or URL}" field="newSource" class="jenkins-form-item--small" >
41-
<f:textbox checkUrl="checkNewSource" checkDependsOn="newSource"/>
42-
</f:entry>
43-
<f:block>
44-
<f:submit name="replace" value="${%Apply new configuration}"/>
45-
</f:block>
46-
</f:form>
47-
</l:isAdmin>
48-
4980
<l:hasPermission permission="${app.SYSTEM_READ}">
50-
<h2>${%Reference}</h2>
51-
<dt>
52-
<dl><a href="reference">${%Documentation}</a></dl>
53-
<dl><a href="schema">${%JSON schema}</a></dl>
54-
</dt>
81+
<f:section title="${%Reference}">
82+
<dt>
83+
<dl>
84+
<a href="reference">${%Documentation}</a>
85+
</dl>
86+
<dl>
87+
<a href="schema">${%JSON schema}</a>
88+
</dl>
89+
</dt>
90+
</f:section>
5591
</l:hasPermission>
56-
</l:main-panel>
57-
</l:layout>
92+
</l:settings-subpage>
5893
</j:jelly>
Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
<?jelly escape-by-default='true'?>
22
<j:jelly xmlns:j="jelly:core" xmlns:l="/lib/layout" xmlns:st="jelly:stapler" xmlns:p="/prism"
33
xmlns:f="/lib/form">
4-
<l:layout type="one-column" title="${%Exported configuration}">
5-
<l:breadcrumb title="${%Exported configuration}" />
6-
<l:main-panel>
7-
<st:adjunct includes="io.jenkins.plugins.casc.assets.viewExport" />
8-
9-
<l:app-bar title="${%Exported configuration}">
10-
<f:form method="post" action="export" name="export">
11-
<f:submit icon="symbol-download" primary="false" name="export" value="${%Download}"/>
12-
</f:form>
13-
</l:app-bar>
4+
<j:set var="header">
5+
<l:view>
6+
<l:app-bar title="${viewExport.displayName}">
7+
<f:form method="post" action="export" name="export">
8+
<f:submit icon="symbol-download" primary="false" name="export" value="${%Download}"/>
9+
</f:form>
10+
</l:app-bar>
11+
</l:view>
12+
</j:set>
1413

14+
<l:settings-subpage includeBreadcrumb="true" header="${header}" managementLink="${viewExport}" noDefer="true">
15+
<st:adjunct includes="io.jenkins.plugins.casc.assets.viewExport" />
1516

1617
<div class="jenkins-alert jenkins-alert-info">
1718
${%exportWarning}
1819
</div>
1920

2021
<p:prism configuration="${it.prismConfiguration}" />
2122
<pre>
22-
<code class="language-yaml">${export}</code>
23+
<code class="language-yaml">${viewExport.urlName}</code>
2324
</pre>
24-
</l:main-panel>
25-
</l:layout>
25+
</l:settings-subpage>
2626
</j:jelly>

plugin/src/test/java/io/jenkins/plugins/casc/ErrorPageTest.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import java.io.IOException;
88
import java.nio.file.Files;
99
import java.nio.file.Path;
10+
import org.htmlunit.html.HtmlButton;
11+
import org.htmlunit.html.HtmlElementUtil;
1012
import org.htmlunit.html.HtmlForm;
1113
import org.htmlunit.html.HtmlPage;
1214
import org.junit.jupiter.api.BeforeEach;
@@ -47,7 +49,10 @@ private String reloadConfiguration() throws Exception {
4749
System.setProperty(ConfigurationAsCode.CASC_JENKINS_CONFIG_PROPERTY, cascFile.toString());
4850

4951
HtmlPage htmlPage = webClient.goTo("manage/configuration-as-code/");
50-
HtmlForm reload = htmlPage.getFormByName("reload");
52+
HtmlButton button = (HtmlButton) htmlPage.getElementById("btn-open-apply-configuration");
53+
HtmlElementUtil.click(button);
54+
55+
HtmlForm reload = htmlPage.getFormByName("replace");
5156
HtmlPage submit = r.submit(reload);
5257

5358
return submit.asNormalizedText();
@@ -67,7 +72,12 @@ void noConfigurator() throws Exception {
6772

6873
@Test
6974
void noImplementationFoundForSymbol() throws Exception {
70-
String content = "jenkins:\n" + " securityRealm:\n" + " unknown:\n" + " username: \"world\"\n";
75+
String content = """
76+
jenkins:
77+
securityRealm:
78+
unknown:
79+
username: "world"
80+
""";
7181

7282
Files.write(cascFile, content.getBytes());
7383

plugin/src/test/java/io/jenkins/plugins/casc/permissions/Action.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22

33
public enum Action {
44
VIEW_CONFIGURATION("Export configuration"),
5-
APPLY_NEW_CONFIGURATION("Apply new configuration"),
6-
RELOAD_EXISTING_CONFIGURATION("Reload existing configuration"),
5+
APPLY_NEW_CONFIGURATION("Setup configuration"),
76
;
87

98
String buttonText;

plugin/src/test/java/io/jenkins/plugins/casc/permissions/PermissionsTest.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package io.jenkins.plugins.casc.permissions;
22

33
import static io.jenkins.plugins.casc.permissions.Action.APPLY_NEW_CONFIGURATION;
4-
import static io.jenkins.plugins.casc.permissions.Action.RELOAD_EXISTING_CONFIGURATION;
54
import static io.jenkins.plugins.casc.permissions.Action.VIEW_CONFIGURATION;
65
import static java.lang.String.format;
76
import static java.net.HttpURLConnection.HTTP_FORBIDDEN;
@@ -62,7 +61,6 @@ void checkPermissionsForSystemReader(JenkinsRule j) throws Exception {
6261
ImmutableMap.<Action, Boolean>builder()
6362
.put(VIEW_CONFIGURATION, true)
6463
.put(APPLY_NEW_CONFIGURATION, false)
65-
.put(RELOAD_EXISTING_CONFIGURATION, false)
6664
.build());
6765
}
6866

@@ -81,11 +79,7 @@ void checkPermissionsForManager(JenkinsRule j) throws Exception {
8179
JenkinsRule.WebClient webClient = j.createWebClient().withThrowExceptionOnFailingStatusCode(false);
8280

8381
assertUserPermissions(
84-
webClient,
85-
MANAGER,
86-
ImmutableMap.<Action, Boolean>builder()
87-
.put(RELOAD_EXISTING_CONFIGURATION, true)
88-
.build());
82+
webClient, MANAGER, ImmutableMap.<Action, Boolean>builder().build());
8983
}
9084

9185
@Test
@@ -105,7 +99,6 @@ void checkPermissionsForAdmin(JenkinsRule j) throws Exception {
10599
ImmutableMap.<Action, Boolean>builder()
106100
.put(VIEW_CONFIGURATION, true)
107101
.put(APPLY_NEW_CONFIGURATION, true)
108-
.put(RELOAD_EXISTING_CONFIGURATION, true)
109102
.build());
110103
}
111104

pom.xml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@
3939
<properties>
4040
<changelist>999999-SNAPSHOT</changelist>
4141
<gitHubRepo>jenkinsci/configuration-as-code-plugin</gitHubRepo>
42-
<jenkins.baseline>2.504</jenkins.baseline>
43-
<jenkins.version>${jenkins.baseline}.3</jenkins.version>
42+
<jenkins.baseline>2.528</jenkins.baseline>
43+
<!-- TODO change back to baseline once next bom version is out -->
44+
<jenkins.version>2.541.1</jenkins.version>
4445
<tagNameFormat>configuration-as-code-@{project.version}</tagNameFormat>
4546
<plugin-bom.version>5983.v443959746f1f</plugin-bom.version>
4647
<spotless.check.skip>false</spotless.check.skip>

0 commit comments

Comments
 (0)