Skip to content

Commit

Permalink
Fixed problem processing sub children
Browse files Browse the repository at this point in the history
  • Loading branch information
alexander-variacode committed Nov 5, 2024
1 parent cd91466 commit 2ee6fbc
Showing 1 changed file with 115 additions and 32 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.rundeck.plugins.ansible.plugin;

import com.dtolabs.rundeck.core.common.Framework;
import com.dtolabs.rundeck.core.common.INodeEntry;
import com.dtolabs.rundeck.core.common.INodeSet;
import com.dtolabs.rundeck.core.common.NodeEntryImpl;
import com.dtolabs.rundeck.core.common.NodeSetImpl;
Expand Down Expand Up @@ -48,6 +49,7 @@
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
Expand Down Expand Up @@ -132,6 +134,8 @@ public class AnsibleResourceModelSource implements ResourceModelSource, ProxyRun
@Setter
private AnsibleInventoryList.AnsibleInventoryListBuilder ansibleInventoryListBuilder = null;

private Map<String, NodeEntryImpl> ansibleNodes = new HashMap<>();

public AnsibleResourceModelSource(final Framework framework) {
this.framework = framework;
}
Expand Down Expand Up @@ -714,42 +718,121 @@ public void ansibleInventoryList(NodeSetImpl nodes, AnsibleRunner.AnsibleRunnerB

if (isTagMapValid(all, ALL)) {
Map<String, Object> children = InventoryList.getValue(all, CHILDREN);
processChildren(nodes, children, new HashSet<>());
}

if (isTagMapValid(children, CHILDREN)) {
for (Map.Entry<String, Object> pair : children.entrySet()) {
String hostGroup = pair.getKey();
Map<String, Object> hostNames = InventoryList.getType(pair.getValue());
Map<String, Object> hosts = InventoryList.getValue(hostNames, HOSTS);

if (isTagMapValid(hosts, HOSTS)) {
for (Map.Entry<String, Object> hostNode : hosts.entrySet()) {
NodeEntryImpl node = new NodeEntryImpl();
node.setTags(Set.of(hostGroup));
String hostName = hostNode.getKey();
node.setHostname(hostName);
node.setNodename(hostName);
Map<String, Object> nodeValues = InventoryList.getType(hostNode.getValue());

InventoryList.tagHandle(NodeTag.HOSTNAME, node, nodeValues);
InventoryList.tagHandle(NodeTag.USERNAME, node, nodeValues);
InventoryList.tagHandle(NodeTag.OS_FAMILY, node, nodeValues);
InventoryList.tagHandle(NodeTag.OS_NAME, node, nodeValues);
InventoryList.tagHandle(NodeTag.OS_ARCHITECTURE, node, nodeValues);
InventoryList.tagHandle(NodeTag.OS_VERSION, node, nodeValues);
InventoryList.tagHandle(NodeTag.DESCRIPTION, node, nodeValues);

nodeValues.forEach((key, value) -> {
if (value != null) {
node.setAttribute(key, value.toString());
}
});
ansibleNodes.forEach((k, node) -> nodes.putNode(node));
ansibleNodes.clear();
}

nodes.putNode(node);
}
}
}
/**
* Processes the given set of nodes and populates the children map with the results.
*
* @param nodes the set of nodes to process
* @param children a map to be populated with the processed children nodes
* @param tags a set of tags to filter the nodes
* @throws ResourceModelSourceException if an error occurs while processing the nodes
*/
public void processChildren(NodeSetImpl nodes, Map<String, Object> children, HashSet<String> tags) throws ResourceModelSourceException {
if (!isTagMapValid(children, CHILDREN)) {
return;
}

for (Map.Entry<String, Object> pair : children.entrySet()) {

String hostGroup = pair.getKey();
tags.add(hostGroup);
Map<String, Object> hostNames = InventoryList.getType(pair.getValue());

if (hostNames.containsKey(CHILDREN)) {
Map<String, Object> subChildren = InventoryList.getValue(hostNames, CHILDREN);
processChildren(nodes, subChildren, tags);
} else {
processHosts(nodes, hostNames, tags);
tags.clear();
}
}
}

/**
* Processes the hosts within the given host names map and adds them to the nodes set.
*
* @param nodes the set of nodes to populate
* @param hostNames the map containing host names and their attributes
* @param tags the set of tags to apply to the nodes
* @throws ResourceModelSourceException if an error occurs while processing the nodes
*/
public void processHosts(NodeSetImpl nodes, Map<String, Object> hostNames, HashSet<String> tags) throws ResourceModelSourceException {
Map<String, Object> hosts = InventoryList.getValue(hostNames, HOSTS);

if (!isTagMapValid(hosts, HOSTS)) {
return;
}

for (Map.Entry<String, Object> hostNode : hosts.entrySet()) {
NodeEntryImpl node = createNodeEntry(hostNode);
addNode(node, tags);
}
}

/**
* Creates a NodeEntryImpl object from the given host node entry and tags.
*
* @param hostNode the entry containing the host name and its attributes
* @return the created NodeEntryImpl object
*/
public NodeEntryImpl createNodeEntry(Map.Entry<String, Object> hostNode) throws ResourceModelSourceException {
NodeEntryImpl node = new NodeEntryImpl();
//node.setTags(Set.copyOf(tags));
String hostName = hostNode.getKey();
node.setHostname(hostName);
node.setNodename(hostName);
Map<String, Object> nodeValues = InventoryList.getType(hostNode.getValue());

applyNodeTags(node, nodeValues);
nodeValues.forEach((key, value) -> {
if (value != null) {
node.setAttribute(key, value.toString());
}
});

return node;
}

/**
* Applies predefined tags to the given node based on the provided node values.
*
* @param node the node to which the tags will be applied
* @param nodeValues the map containing the node's attributes
*/
public void applyNodeTags(NodeEntryImpl node, Map<String, Object> nodeValues) throws ResourceModelSourceException {
InventoryList.tagHandle(NodeTag.HOSTNAME, node, nodeValues);
InventoryList.tagHandle(NodeTag.USERNAME, node, nodeValues);
InventoryList.tagHandle(NodeTag.OS_FAMILY, node, nodeValues);
InventoryList.tagHandle(NodeTag.OS_NAME, node, nodeValues);
InventoryList.tagHandle(NodeTag.OS_ARCHITECTURE, node, nodeValues);
InventoryList.tagHandle(NodeTag.OS_VERSION, node, nodeValues);
InventoryList.tagHandle(NodeTag.DESCRIPTION, node, nodeValues);
}

public void addNode(NodeEntryImpl node, Set<String> tags) {
if (ansibleNodes.containsKey(node.getNodename())) {
NodeEntryImpl oldNode = ansibleNodes.get(node.getNodename());
Set<String> currentTags = getStringTags(oldNode);
currentTags.addAll(tags);
oldNode.setTags(Set.copyOf(currentTags));
} else {
node.setTags(Set.copyOf(tags));
ansibleNodes.put(node.getNodename(), node);
}
}

public Set<String> getStringTags(NodeEntryImpl node) {
Set<String> tags = new HashSet<>();
for (Object tag : node.getTags()) {
tags.add(tag.toString());
}
return tags;
}

/**
Expand Down

0 comments on commit 2ee6fbc

Please sign in to comment.