public void deleteTask(String id) { Optional<String> scid = getSwarmClusterId(); if (scid.isPresent()) { dockerScanner.getNeoRxClient().execCypher( "match (s:DockerSwarm {swarmClusterId:{swarmClusterId}})--(x:DockerTask {taskId:{taskId}}) detach delete x", "taskId", id, "swarmClusterId", scid.get()); dockerScanner.getNeoRxClient().execCypher( "match (x:DockerTask {taskId:{taskId}, swarmClusterId:{swarmClusterId}}) detach delete x", "taskId", id, "swarmClusterId", scid.get()); } return; }
public void deleteNode(String id) { Optional<String> scid = getSwarmClusterId(); if (scid.isPresent()) { dockerScanner.getNeoRxClient().execCypher( "match (s:DockerSwarm {swarmClusterId:{swarmClusterId}})--(x:DockerHost {swarmNodeId:{swarmNodeId}}) detach delete x", "swarmNodeId", id, "swarmClusterId", scid.get()); dockerScanner.getNeoRxClient().execCypher( "match (x:DockerHost {swarmNodeId:{swarmNodeId}, swarmClusterId:{swarmClusterId}}) detach delete x", "swarmNodeId", id, "swarmClusterId", scid.get()); } return; }
private void updateEngineInfo(JsonNode nodeInfo) { ObjectNode n = new ObjectMapper().createObjectNode(); n.set("engineId", nodeInfo.get("ID")); n.put("architecture", nodeInfo.path("Architecture").asText()); n.put("osType", nodeInfo.path("OSType").asText()); n.put("operatingSystem", nodeInfo.path("OperatingSystem").asText()); n.put("kernelVersion", nodeInfo.path("KernelVersion").asText()); n.put("serverVersion", nodeInfo.path("ServerVersion").asText()); n.put("nCPU", nodeInfo.path("NCPU").asLong()); n.put("memTotal", nodeInfo.path("MemTotal").asLong()); n.path("Labels").fields().forEachRemaining(it -> { String labelKey = "label_" + it.getKey(); n.set(labelKey, it.getValue()); }); getNeoRxClient().execCypher("merge (h:DockerHost {engineId:{engineId}}) set h+={props}, h.updateTs=timestamp()","engineId",n.path("engineId").asText(),"props",n); } @Override
public void deleteService(String id) { Optional<String> scid = getSwarmClusterId(); if (scid.isPresent()) { logger.info("deleting neo4j DockerService id/name={}", id); dockerScanner.getNeoRxClient().execCypher( "match (x:DockerService {name:{name},swarmClusterId:{swarmClusterId}}) detach delete x", "name", id, "swarmClusterId", scid.get()); dockerScanner.getNeoRxClient().execCypher( "match (x:DockerService {serviceId:{serviceId},swarmClusterId:{swarmClusterId}}) detach delete x", "serviceId", id, "swarmClusterId", scid.get()); dockerScanner.getNeoRxClient().execCypher( "match (s:DockerSwarm {swarmClusterId:{swarmClusterId}})--(x:DockerService {serviceId:{serviceId}}) detach delete x", "serviceId", id, "swarmClusterId", scid.get()); dockerScanner.getNeoRxClient().execCypher( "match (s:DockerSwarm {swarmClusterId:{swarmClusterId}})--(x:DockerService {name:{name}}) detach delete x", "name", id, "swarmClusterId", scid.get()); } }
long saveDockerNode(String swarmClusterId, JsonNode n) { String swarmNodeId = n.get("swarmNodeId").asText(); AtomicLong updateTs = new AtomicLong(Long.MAX_VALUE); dockerScanner.getNeoRxClient() .execCypher( "merge (n:DockerHost {swarmNodeId:{nodeId}}) set n+={props}, n.updateTs=timestamp() return n", "nodeId", swarmNodeId, "props", n) .forEach(actual -> { removeDockerLabels("DockerHost", "swarmNodeId", swarmNodeId, n, actual); updateTs.set(Math.min(updateTs.get(), actual.path("updateTs").asLong(Long.MAX_VALUE))); }); logger.info("connecting swarm={} to node={}", swarmClusterId, swarmNodeId); dockerScanner.getNeoRxClient().execCypher( "match (s:DockerSwarm {swarmClusterId:{swarmClusterId}}), (n:DockerHost {swarmNodeId:{nodeId}}) merge (s)-[x:CONTAINS]->(n) set x.updateTs=timestamp()", "swarmClusterId", swarmClusterId, "nodeId", swarmNodeId); return updateTs.get(); }
/** * Removes labels that were present from a scan, but subsequently removed. * * @param neo4jLabel * @param idName * @param idVal * @param intended * @param actual */ protected void removeDockerLabels(String neo4jLabel, String idName, String idVal, JsonNode intended, JsonNode actual) { List<String> x = Lists.newArrayList(); actual.fieldNames().forEachRemaining(it -> { if (it != null && it.startsWith("label_")) { if (!intended.has(it)) { if (!it.contains(" ")) { x.add("a.`" + it + "`"); } } } }); if (!x.isEmpty()) { String cypher = "match (a:" + neo4jLabel + " {" + idName + ":{id}}) remove " + Joiner.on(", ").join(x) + " return a"; dockerScanner.getNeoRxClient().execCypher(cypher, "id", idVal); } }
public void scanTasksForSwarm(String swarmClusterId) { logger.info("scanning tasks for swarm: {}", swarmClusterId); AtomicLong earlistUpdate = new AtomicLong(Long.MAX_VALUE); AtomicBoolean error = new AtomicBoolean(false); JsonNode response = getRestClient().getTasks(); response.forEach(it -> { try { earlistUpdate.set(Math.min(earlistUpdate.get(), saveTask(it))); } catch (Exception e) { logger.warn("problem updating task", e); error.set(true); } }); if (error.get() == false) { if (earlistUpdate.get() < System.currentTimeMillis()) { dockerScanner.getNeoRxClient().execCypher( "match (x:DockerTask) where x.swarmClusterId={swarmClusterId} and x.updateTs<{cutoff} detach delete x", "cutoff", earlistUpdate.get(), "swarmClusterId", swarmClusterId); } } }
ObjectNode n = flattenService(it); n.put("swarmClusterId", swarmClusterId); dockerScanner.getNeoRxClient().execCypher( "merge (x:DockerService {serviceId:{serviceId}}) set x+={props}, x.updateTs=timestamp() return x", "serviceId", n.get("serviceId").asText(), "props", n).forEach(svc -> { .set(Math.min(earlistUpdate.get(), svc.path("updateTs").asLong(Long.MAX_VALUE))); }); dockerScanner.getNeoRxClient().execCypher( "match (swarm:DockerSwarm {swarmClusterId:{swarmClusterId}}),(service:DockerService{serviceId:{serviceId}}) merge (swarm)-[x:CONTAINS]->(service) set x.updateTs=timestamp()", "swarmClusterId", swarmClusterId, "serviceId", n.path("serviceId").asText()); if (error.get() == false) { if (earlistUpdate.get() < System.currentTimeMillis()) { dockerScanner.getNeoRxClient().execCypher( "match (x:DockerService) where x.swarmClusterId={swarmClusterId} and x.updateTs<{cutoff} detach delete x", "cutoff", earlistUpdate.get(), "swarmClusterId", swarmClusterId);
dockerScanner.getNeoRxClient() .execCypher("merge (x:DockerTask {taskId:{taskId}}) set x+={props}, x.updateTs=timestamp() return x", "taskId", taskId, "props", n) dockerScanner.getNeoRxClient().execCypher( "match (s:DockerService {serviceId:{serviceId}}),(t:DockerTask{taskId:{taskId}}) merge (s)-[x:CONTAINS]->(t) set x.updateTs=timestamp() return t,s", "serviceId", serviceId, "taskId", taskId); if (!Strings.isNullOrEmpty(swarmNodeId)) { dockerScanner.getNeoRxClient().execCypher( "match (h:DockerHost {swarmNodeId:{swarmNodeId}}), (t:DockerTask {swarmNodeId:{swarmNodeId}}) merge (h)-[x:RUNS]->(t) set x.updateTs=timestamp()", "swarmNodeId", swarmNodeId);
props.put("updatedAt", updatedAt); JsonNode swarmNode = dockerScanner.getNeoRxClient() .execCypher( "merge (c:DockerSwarm {swarmClusterId:{id}}) set c+={props},c.updateTs=timestamp() return c", dockerScanner.getNeoRxClient().execCypher("match (c:DockerSwarm {name:{name}}) return c", "name", name) .forEach(it -> { String oldSwarmClusterId = it.path("swarmClusterId").asText(); if (!swarmClusterId.equals(oldSwarmClusterId)) { dockerScanner.getNeoRxClient().execCypher( "match (c:DockerSwarm {swarmClusterId:{swarmClusterId}}) detach delete c", "swarmClusterId", oldSwarmClusterId); dockerScanner.getNeoRxClient().execCypher( "match (c:DockerSwarm {swarmClusterId:{id}}) set c.managerApiUrl={managerApiUrl},c.name={name},c.tridentClusterId={name} return c", "id", swarmClusterId, "managerApiUrl", LOCAL_DOCKER_DAEMON_SOCKET_URL, "name", name); if (earliestTimestamp.get() < System.currentTimeMillis()) { logger.info("deleting DockerHost nodes before with updateTs<{}", earliestTimestamp.get()); dockerScanner.getNeoRxClient().execCypher( "match (s:DockerSwarm {swarmClusterId:{id}})--(x:DockerHost) where s.updateTs>x.updateTs detach delete x", "id", swarmClusterId);
public void scanService(String id) { try { Optional<String> scid = getSwarmClusterId(); if (scid.isPresent()) { logger.info("performing targeted scan of service={}", id); JsonNode it = getRestClient().getService(id); ObjectNode n = flattenService(it); n.put("swarmClusterId", scid.get()); dockerScanner.getNeoRxClient().execCypher( "merge (x:DockerService {serviceId:{serviceId}}) set x+={props}, x.updateTs=timestamp() return x", "serviceId", n.get("serviceId").asText(), "props", n).forEach(actual -> { try { removeDockerLabels("DockerService", "serviceId", n.get("serviceId").asText(), n, actual); } catch (Exception e) { logger.warn("problem removing labels: " + e.toString()); } }); dockerScanner.getNeoRxClient().execCypher( "match (swarm:DockerSwarm {swarmClusterId:{swarmClusterId}}),(service:DockerService{serviceId:{serviceId}}) merge (swarm)-[x:CONTAINS]->(service) set x.updateTs=timestamp()", "swarmClusterId", scid.get(), "serviceId", n.path("serviceId").asText()); } } catch (RuntimeException e) { if (isNotFound(e)) { deleteService(id); return; } throw e; } }
@BeforeClass public static void setupDockerScanner() { DockerScanner ds = new Projector.Builder().build().createBuilder(DockerScannerBuilder.class).withLocalDockerDaemon().build(); boolean b = ds.getNeoRxClient().checkConnection(); if (b==false) { logger.warn("neo4j is not available...integration tests will be skipped"); Assume.assumeTrue("neo4j available", b); } else { logger.info("neo4j is available for integration tests"); } try { Info info = ds.getDockerClient().infoCmd().exec(); logger.info("local docker daemon is available for integration tests"); dockerScanner = ds; } catch (Exception e) { logger.warn("neo4j is not available for integration tests",e); Assume.assumeTrue(false); return; } } }