package database import ( "log" "github.com/neo4j/neo4j-go-driver/neo4j" ) //Database type Database struct { driver neo4j.Driver session neo4j.Session } //NewDatabaseClient creates a database client func NewDatabaseClient(uri, username, password string, encrypted bool) Database { //TODO: defer close()? // probably pretty nasty since it creates copies driver := createDriver(uri, username, password, encrypted) session := createSession(driver) return Database{ driver: driver, session: session, } } //createDriver creates a neo4j.Driver instance func createDriver(uri, username, password string, encrypted bool) neo4j.Driver { driver, err := neo4j.NewDriver( uri, neo4j.BasicAuth(username, password, ""), func(c *neo4j.Config) { c.Encrypted = encrypted }, ) logError("failed creating database Driver", err) return driver } //createSession creates a neo4j.Session func createSession(driver neo4j.Driver) neo4j.Session { sessionConfig := neo4j.SessionConfig{AccessMode: neo4j.AccessModeWrite} session, err := driver.NewSession(sessionConfig) logError("failed creating database session", err) return session } //StoreNodes stores the given nodes to the database func (d Database) StoreNodes(json string) { session := d.session query := ` WITH apoc.convert.fromJsonMap($stringToAdd) AS value UNWIND value.data as d MERGE (device:Device {id: d.object_id}) ON CREATE SET device.nativeName = d.object_data.name[0].value, device.deviceType = d.object_data.name[1].value, device.serialNumber = d.object_data.name[2].value, device.softwareVersion = d.object_data.name[3].value, device.` + "`operational-state` = d.object_data.`operational-state`" _, err := session.Run( query, map[string]interface{}{ "stringToAdd": json, }) logError("failed storing Nodes into database", err) log.Printf("successfully added Nodes into database") } //StoreNodeEdgePoints stores the given node edge points (interfaces) func (d Database) StoreNodeEdgePoints(json string) { session := d.session queryEdgePoints := ` WITH apoc.convert.fromJsonMap($stringToAdd) AS value UNWIND value.data as i MERGE (interface:Interface {id: i.object_id}) ON CREATE SET interface.object_type =i.object_type, interface.localId = i.object_data.name[0].value, interface.location = i.object_data.name[1].value, interface.` + "`containing-node` = i.object_data.`containing-node`" _, err := session.Run( queryEdgePoints, map[string]interface{}{ "stringToAdd": json, }) logError("failed storing NodeEdgePoints into database", err) setNodeNodeEdgePointsRelation(session) log.Printf("successfully added NodeEdgePoints into database") } //setNodeNodeEdgePointsRelation creates the database relations between "nodes" and "node edge points" func setNodeNodeEdgePointsRelation(session neo4j.Session) { query := ` MATCH (d:Device), (i:Interface) WHERE d.id = i.` + "`containing-node`" + ` CREATE (i)-[:BELONGS_TO]->(d) ` _, err := session.Run( query, map[string]interface{}{}) logError("failed storing NodeNodeEdgePointsRelation into database", err) log.Printf("successfully stored NodeNodeEdgePointsRelation into database") } //logError logs error with custom and error message func logError(message string, err error) { if err != nil { log.Fatalf("%v: %v", message, err) } }