diff --git a/src/main/java/com/michelin/cio/hudson/plugins/rolestrategy/RoleBasedAuthorizationStrategy.java b/src/main/java/com/michelin/cio/hudson/plugins/rolestrategy/RoleBasedAuthorizationStrategy.java index dbb77ef9..f2d9393c 100644 --- a/src/main/java/com/michelin/cio/hudson/plugins/rolestrategy/RoleBasedAuthorizationStrategy.java +++ b/src/main/java/com/michelin/cio/hudson/plugins/rolestrategy/RoleBasedAuthorizationStrategy.java @@ -528,6 +528,29 @@ public void doGetMatchingJobs(@QueryParameter(required = true) String pattern, writer.close(); } + /** + * API method to get a list of agents matching a pattern + * Example: curl -X GET localhost:8080/role-strategy/strategy/getMatchingAgents?pattern=^linux.* + * + * @param pattern Pattern to match against + * @param maxAgents Maximum matching agents to search for + * @throws IOException when unable to write response + */ + @GET + @Restricted(NoExternalUse.class) + public void doGetMatchingAgents(@QueryParameter(required = true) String pattern, + @QueryParameter() int maxAgents) throws IOException { + checkAdminPerm(); + List matchingAgents = RoleMap.getMatchingAgentNames(Pattern.compile(pattern), maxAgents); + JSONObject responseJson = new JSONObject(); + responseJson.put("matchingAgents", matchingAgents); + StaplerResponse response = Stapler.getCurrentResponse(); + response.setContentType("application/json;charset=UTF-8"); + Writer writer = response.getCompressedWriter(Stapler.getCurrentRequest()); + responseJson.write(writer); + writer.close(); + } + @Extension public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl(); diff --git a/src/main/java/com/michelin/cio/hudson/plugins/rolestrategy/RoleMap.java b/src/main/java/com/michelin/cio/hudson/plugins/rolestrategy/RoleMap.java index 871030a6..f9f1e2f9 100644 --- a/src/main/java/com/michelin/cio/hudson/plugins/rolestrategy/RoleMap.java +++ b/src/main/java/com/michelin/cio/hudson/plugins/rolestrategy/RoleMap.java @@ -34,6 +34,7 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.model.Item; import hudson.model.ItemGroup; +import hudson.model.Node; import hudson.model.User; import hudson.security.AccessControlled; import hudson.security.Permission; @@ -439,6 +440,23 @@ public static List getMatchingJobNames(Pattern pattern, int maxJobs) { return matchingJobNames; } + /** + * Get all agent names matching the given pattern, viewable to the requesting user + * @param pattern Pattern to match against + * @param maxAgents Max matching agents to look for + * @return List of matching agent names + */ + public static List getMatchingAgentNames(Pattern pattern, int maxAgents) { + List matchingAgentNames = new ArrayList<>(); + for (Node node: Jenkins.get().getNodes()) { + if (pattern.matcher(node.getNodeName()).matches()) { + matchingAgentNames.add(node.getNodeName()); + if (matchingAgentNames.size() >= maxAgents) break; + } + } + return matchingAgentNames; + } + /** * The Acl class that will delegate the permission check to the {@link RoleMap} object. */ diff --git a/src/main/resources/com/michelin/cio/hudson/plugins/rolestrategy/RoleStrategyConfig/manage-agent-roles.jelly b/src/main/resources/com/michelin/cio/hudson/plugins/rolestrategy/RoleStrategyConfig/manage-agent-roles.jelly index 5d070a0c..1e7c30f0 100644 --- a/src/main/resources/com/michelin/cio/hudson/plugins/rolestrategy/RoleStrategyConfig/manage-agent-roles.jelly +++ b/src/main/resources/com/michelin/cio/hudson/plugins/rolestrategy/RoleStrategyConfig/manage-agent-roles.jelly @@ -170,7 +170,8 @@ var child = copy.childNodes[1]; var doubleQuote = '"'; child.innerHTML = escapeHTML(name); - child.next().innerHTML = doubleQuote + escapeHTML(pattern) + doubleQuote; + var patternString = doubleQuote + escapeHTML(pattern) + doubleQuote; + child.next().innerHTML = '' + patternString + ''; var hidden = document.createElement('input'); hidden.setAttribute('name', '[pattern]'); @@ -185,6 +186,10 @@ item.outerHTML = item.outerHTML.replace("{{ROLE}}", doubleEscapeHTML(name)).replace("{{PATTERN}}", doubleEscapeHTML(pattern)); }); + child = copy.childNodes[1]; + var link = child.next().children[0]; + bindAgentListenerToPattern(link); + table.appendChild(copy); @@ -196,8 +201,62 @@ }); })(); + var bindAgentListenerToPattern = function(elem) { + elem.addEventListener('click', showMatchingAgents); + } + + var showMatchingAgents = function() { + var pattern = this.text.substring(1, this.text.length - 1); // Ignore quotes for the pattern + var maxAgents = 10; // Maximum agents to search for + var url = 'strategy/getMatchingAgents'; + reqParams = { + 'pattern' : pattern, + 'maxAgents' : maxAgents + } + + new Ajax.Request(url, { + method: 'get', + parameters: reqParams, + onSuccess: function(req) { + var matchingAgents = req.responseText.evalJSON().matchingAgents; + + if(matchingAgents != null) { + showAgentsModal(matchingAgents); + } else { + showAgentErrorMessageModal(); + } + }, + onFailure: showAgentErrorMessageModal + }); + } + + var showAgentsModal = function(agents) { + modalText = ''; + if(agents.length > 0) { + modalText += 'Matching Agents:\n\n'; + for(var i = 0; i != agents.length; i++) { + modalText += ' - ' + agents[i] + '\n'; + } + } else { + modalText += 'No matching Agents found.'; + } + modalText += '\n\n'; + alert(modalText); + } + + var showAgentErrorMessageModal = function() { + alert('Unable to fetch matching Agents.'); + } + Event.observe(window, 'load', function(event) { agentTableHighlighter = new TableHighlighter('agentRoles', 3, 2); + // Show agents matching a pattern on click + var agentRolesTable = document.getElementById('agentRoles') + var patterns = agentRolesTable.getElementsByClassName('patternAnchor'); + for(var i = 0; i != patterns.length; i++) { + bindAgentListenerToPattern(patterns[i]); + } + }); var deleteAgentRole = function(e) { @@ -217,7 +276,9 @@ this.innerHTML = ''; } else { - this.innerHTML = this.childNodes[0].value.escapeHTML() + ''; + this.innerHTML = '"' + this.childNodes[0].value.escapeHTML() + '"'; + child = this.children[0]; + bindAgentListenerToPattern(this.children[0]); } return false; } diff --git a/src/main/resources/com/michelin/cio/hudson/plugins/rolestrategy/RoleStrategyConfig/manage-project-roles.jelly b/src/main/resources/com/michelin/cio/hudson/plugins/rolestrategy/RoleStrategyConfig/manage-project-roles.jelly index 9b9840b5..e4760750 100644 --- a/src/main/resources/com/michelin/cio/hudson/plugins/rolestrategy/RoleStrategyConfig/manage-project-roles.jelly +++ b/src/main/resources/com/michelin/cio/hudson/plugins/rolestrategy/RoleStrategyConfig/manage-project-roles.jelly @@ -126,7 +126,7 @@