From ca4e9d435e2bdb11930045b534c1e4184d166024 Mon Sep 17 00:00:00 2001
From: Matthew Zane <mzane@ucsd.edu>
Date: Wed, 31 Aug 2022 03:50:24 +0900
Subject: [PATCH] Added Regions to G2 Visualization

---
 Plugins/Reztly                                |   2 +-
 .../Private/G2TopologyController.cpp          | 119 ++++++++++++------
 .../arnocMain/Public/G2TopologyController.h   |  31 +++--
 3 files changed, 104 insertions(+), 48 deletions(-)

diff --git a/Plugins/Reztly b/Plugins/Reztly
index 970802b..dfc1d41 160000
--- a/Plugins/Reztly
+++ b/Plugins/Reztly
@@ -1 +1 @@
-Subproject commit 970802b079e0c2031aa0dcb5448d750c78c9f97f
+Subproject commit dfc1d41acbea5522f3bffd97c9c2b23ea3ba2da1
diff --git a/Source/arnocMain/Private/G2TopologyController.cpp b/Source/arnocMain/Private/G2TopologyController.cpp
index ea5ac38..c1b0174 100644
--- a/Source/arnocMain/Private/G2TopologyController.cpp
+++ b/Source/arnocMain/Private/G2TopologyController.cpp
@@ -35,7 +35,7 @@ UG2Snapshot* AG2TopologyController::GetSnapshot()
 
 void AG2TopologyController::RequestBearerToken()
 {
-	FResponseDelegate Delegate;
+	FStringResponseDelegate Delegate;
 	Delegate.BindUFunction(this, FName("OnBearerTokenResponse"));
 	UReztly::RequestBearerToken(G2Username, G2Password, G2APIURL, Delegate);
 }
@@ -58,7 +58,7 @@ void AG2TopologyController::OnBearerTokenResponse(FString ResponseContentString,
 
 void AG2TopologyController::RequestSnapshotRange()
 {
-	FResponseDelegate Delegate;
+	FStringResponseDelegate Delegate;
 	Delegate.BindUFunction(this, FName("OnSnapshotRangeResponse"));
 	UReztly::RequestSnapshotRange(G2APIURL, G2Token, Delegate);
 }
@@ -89,7 +89,7 @@ void AG2TopologyController::RequestLatestSnapshot() {
 }
 
 void AG2TopologyController::RequestSnapshot(int SnapshotID) {
-	FResponseDelegate Delegate;
+	FStringResponseDelegate Delegate;
 	Delegate.BindUFunction(this, FName("OnSnapshotResponse"));
 	UReztly::RequestSnapshot(SnapshotID, G2APIURL, G2Token, Delegate);
 }
@@ -129,7 +129,49 @@ void AG2TopologyController::ParseG2Snapshot(FG2SnapshotResponse SnapshotIn) {
 
 	UE_LOG(LogTemp, Log, TEXT("Finished Parsing G2 Data."));
 
-	RequestNetboxSitesGet();
+	RequestNetboxRegionsGet();
+}
+
+void AG2TopologyController::ParseRegionData(TArray<FRegionStruct> NetboxRegions)
+{
+	for (FRegionStruct NetboxRegion : NetboxRegions)
+	{
+		URegion* Region = NewObject<URegion>();
+
+		Region->ID = NetboxRegion.Id;
+		Region->Url = NetboxRegion.Url;
+		Region->Display = NetboxRegion.Display;
+		Region->Name = NetboxRegion.Name;
+		Region->Slug = NetboxRegion.Slug;
+		Region->ParentName = NetboxRegion.Parent.Name;
+		Region->Description = NetboxRegion.Description;
+
+		Region->LogoUrl = NetboxRegion.Custom_fields.Logo;
+		Region->Latitude = FCString::Atof(*NetboxRegion.Custom_fields.Region_latitude);
+		Region->Longitude = FCString::Atof(*NetboxRegion.Custom_fields.Region_longitude);
+
+		NameToRegionMap.Add(Region->Name, Region);
+	}
+}
+
+void AG2TopologyController::ParseSiteData(TArray<FSiteStruct> NetboxSites)
+{
+	for (FSiteStruct NetboxSite : NetboxSites)
+	{
+		USite* Site = NewObject<USite>();
+
+		Site->ID = NetboxSite.Id;
+		Site->Url = NetboxSite.Url;
+		Site->Display = NetboxSite.Display;
+		Site->Name = NetboxSite.Name;
+		Site->Slug = NetboxSite.Slug;
+		Site->RegionName = NetboxSite.Region.Name;
+
+		Site->Latitude = NetboxSite.Latitude;
+		Site->Longitude = NetboxSite.Longitude;
+
+		NameToSiteMap.Add(Site->Name, Site);
+	}
 }
 
 void AG2TopologyController::ParseNodeData(TArray<FG2NodeStruct> SnapshotNodes) {
@@ -265,25 +307,6 @@ void AG2TopologyController::ParseNodeInfo(FString Info, FString& IPAddress,
 	}
 }
 
-void AG2TopologyController::ParseSiteData(TArray<FSiteStruct> NetboxSites)
-{
-	for (FSiteStruct NetboxSite : NetboxSites)
-	{
-		USite* Site = NewObject<USite>();
-
-		Site->ID = NetboxSite.Id;
-		Site->Url = NetboxSite.Url;
-		Site->Display = NetboxSite.Display;
-		Site->Name = NetboxSite.Name;
-		Site->Slug = NetboxSite.Slug;
-
-		Site->Latitude = NetboxSite.Latitude;
-		Site->Longitude = NetboxSite.Longitude;
-
-		NameToSiteMap.Add(Site->Name, Site);
-	}
-}
-
 void AG2TopologyController::ReplaceFlowLinkNodeIDs(TArray<FFlowLink>& FlowLinks,
 	UG2Node* StartNode,
 	UG2Node* EndNode) {
@@ -296,9 +319,37 @@ void AG2TopologyController::ReplaceFlowLinkNodeIDs(TArray<FFlowLink>& FlowLinks,
 	}
 }
 
+void AG2TopologyController::RequestNetboxRegionsGet() 
+{
+	FStringResponseDelegate Delegate;
+	Delegate.BindUFunction(this, FName("OnNetboxRegionsGetResponse"));
+	UReztly::RequestNetboxRegionsGet(NetboxURL, NetboxToken, Delegate);
+}
+
+void AG2TopologyController::OnNetboxRegionsGetResponse(
+	FString ResponseContentString,
+	bool bWasSuccessful) 
+{
+	if (bWasSuccessful && !ResponseContentString.Contains("\"error\": \"connection to server at")) {
+		UE_LOG(LogTemp, Log, TEXT("Netbox Request Successful"));
+		UE_LOG(LogTemp, Log, TEXT("Response Body: %s"),
+			*ResponseContentString);
+
+		FNetboxRegionResponse NetboxRegionResponse =
+			UJsonParser::StringToNetboxRegionResponse(ResponseContentString);
+
+		ParseRegionData(NetboxRegionResponse.Results);
+
+		RequestNetboxSitesGet();
+	}
+	else {
+		UE_LOG(LogTemp, Warning, TEXT("Netbox Request Unsuccessful"));
+	}
+}
+
 void AG2TopologyController::RequestNetboxSitesGet()
 {
-	FResponseDelegate Delegate;
+	FStringResponseDelegate Delegate;
 	Delegate.BindUFunction(this, FName("OnNetboxSitesGetResponse"));
 	UReztly::RequestNetboxSitesGet(NetboxURL, NetboxToken, Delegate);
 }
@@ -325,7 +376,7 @@ void AG2TopologyController::OnNetboxSitesGetResponse(FString ResponseContentStri
 
 void AG2TopologyController::RequestNetboxSitePatch(FSiteStruct Site)
 {
-	FResponseDelegate Delegate;
+	FStringResponseDelegate Delegate;
 	Delegate.BindUFunction(this, FName("OnNetboxSitePatchResponse"));
 	UReztly::RequestNetboxSitePatch(Site, NetboxURL, NetboxToken, Delegate);
 }
@@ -345,7 +396,7 @@ void AG2TopologyController::OnNetboxSitePatchResponse(FString ResponseContentStr
 
 void AG2TopologyController::RequestNetboxDevicesGet()
 {
-	FResponseDelegate Delegate;
+	FStringResponseDelegate Delegate;
 	Delegate.BindUFunction(this, FName("OnNetboxDevicesResponse"));
 	UReztly::RequestNetboxDevicesGet(NetboxURL, NetboxToken, Delegate);
 }
@@ -409,11 +460,6 @@ void AG2TopologyController::ParseNetboxDeviceData(FNetboxDeviceResponse NetboxRe
 
 			USite* Site = Node->Device->Site;
 
-			if (!Node->Device->NodeIDs.Contains(Node->ID))
-			{
-				Node->Device->NodeIDs.Add(Node->ID);
-			}
-
 			if (!Site->Name.Equals("TBD") && !CompareNodeToNetboxDeviceData(Node))
 			{
 				if (!IsValidLatLong(Node->Latitude, Node->Longitude))
@@ -445,14 +491,12 @@ void AG2TopologyController::ParseNetboxDeviceData(FNetboxDeviceResponse NetboxRe
 			NewDevice->Primary = Node->Primary;
 
 			Node->Device = NewDevice;
-			Node->Device->NodeIDs.Add(Node->ID);
 
 			NewDevices.Add(NewDevice);
 			NameToDeviceMap.Add(NewDevice->Name, NewDevice);
 		}
 		else {
 			Node->Device = NameToDeviceMap["TBD"];
-			Node->Device->NodeIDs.Add(Node->ID);
 		}
 	}
 
@@ -498,8 +542,7 @@ bool AG2TopologyController::CompareNodeToNetboxDeviceData(UG2Node* Node) {
 		Node->IP = Node->Device->IP;
 	}
 
-	return Node->Device->NodeIDs.Contains(Node->ID) &&
-		Node->MTU == Node->MTU;
+	return Node->MTU == Node->MTU;
 }
 
 void AG2TopologyController::RequestNetboxDevicesPost()
@@ -512,7 +555,7 @@ void AG2TopologyController::RequestNetboxDevicesPost()
 
 	UE_LOG(LogTemp, Log, TEXT("Device Post Request %d/%d"), CurrentNewBatch, NumNewBatches);
 
-	FResponseDelegate Delegate;
+	FStringResponseDelegate Delegate;
 	Delegate.BindUFunction(this, FName("OnNetboxPostDeviceResponse"));
 	UReztly::RequestNetboxDevicesPost(DeviceBatch, NetboxURL, NetboxToken, Delegate);
 
@@ -573,7 +616,7 @@ void AG2TopologyController::RequestNetboxDevicesPatch()
 
 	UE_LOG(LogTemp, Log, TEXT("Device Patch Request %d/%d"), CurrentUpdateDevice, NumUpdateBatches);
 
-	FResponseDelegate Delegate;
+	FStringResponseDelegate Delegate;
 	Delegate.BindUFunction(this, FName("OnNetboxPatchDeviceResponse"));
 	UReztly::RequestNetboxDevicesPatch(DeviceBatch, NetboxURL, NetboxToken, Delegate);
 }
@@ -581,7 +624,7 @@ void AG2TopologyController::RequestNetboxDevicesPatch()
 void AG2TopologyController::RequestNetboxDevicePatch(UDevice* Device)
 {
 	DevicesToUpdate.Add(Device);
-	FResponseDelegate Delegate;
+	FStringResponseDelegate Delegate;
 	Delegate.BindUFunction(this, FName("OnNetboxPatchDeviceResponse"));
 
 	TArray<FDeviceStruct> Devices;
diff --git a/Source/arnocMain/Public/G2TopologyController.h b/Source/arnocMain/Public/G2TopologyController.h
index 19d86f1..fe9a527 100644
--- a/Source/arnocMain/Public/G2TopologyController.h
+++ b/Source/arnocMain/Public/G2TopologyController.h
@@ -8,6 +8,7 @@
 
 #include "G2SnapshotResponse.h"
 #include "G2Snapshot.h"
+#include "Region.h"
 #include "Site.h"
 #include "NetboxDeviceResponse.h"
 #include "NetboxSiteResponse.h"
@@ -55,6 +56,9 @@ public:
 	UPROPERTY(BlueprintReadWrite, EditAnywhere)
 		TMap<FString, UDevice*> NameToDeviceMap;
 
+	UPROPERTY(BlueprintReadWrite, EditAnywhere)
+		TMap<FString, URegion*> NameToRegionMap;
+
 	UPROPERTY(BlueprintReadWrite, EditAnywhere)
 		int MaxEntriesPerRequest = 10;
 
@@ -108,18 +112,21 @@ public:
 		void RequestSnapshot(int SnapshotID);
 	UFUNCTION(BlueprintCallable)
 		void OnSnapshotResponse(FString ResponseContentString,
-			bool bWasSuccessful);
+								bool bWasSuccessful);
 
 	UFUNCTION(BlueprintCallable)
 		void ParseG2Snapshot(FG2SnapshotResponse SnapshotIn);
+	UFUNCTION(BlueprintCallable)
+		void ParseRegionData(TArray<FRegionStruct> NetboxRegions);
+	UFUNCTION(BlueprintCallable)
+		void ParseSiteData(TArray<FSiteStruct> NetboxSites);
 	UFUNCTION(BlueprintCallable)
 		void ParseNodeData(TArray<FG2NodeStruct> SnapshotNodes);
 	UFUNCTION(BlueprintCallable)
 		void ParseLinkData(TArray<FLink> SnapshotLinks);
 	UFUNCTION(BlueprintCallable)
 		void ParseFlowData(TArray<FFlow> SnapshotFlows);
-	UFUNCTION(BlueprintCallable)
-		void ParseSiteData(TArray<FSiteStruct> NetboxSites);
+
 
 	UFUNCTION(BlueprintCallable)
 		void ParseNodeInfo(FString Info, FString& IPAddress, float& MTU);
@@ -128,22 +135,28 @@ public:
 			UG2Node* StartNode, UG2Node* EndNode);
 
 	UFUNCTION(BlueprintCallable)
-		void RequestNetboxDevicesGet();
+		void RequestNetboxRegionsGet();
 	UFUNCTION(BlueprintCallable)
-		void OnNetboxDevicesResponse(FString ResponseContentString,
+		void OnNetboxRegionsGetResponse(FString ResponseContentString,
 			bool bWasSuccessful);
 
 	UFUNCTION(BlueprintCallable)
 		void RequestNetboxSitesGet();
 	UFUNCTION(BlueprintCallable)
 		void OnNetboxSitesGetResponse(FString ResponseContentString,
-			bool bWasSuccessful);
+									  bool bWasSuccessful);
 
 	UFUNCTION(BlueprintCallable)
 		void RequestNetboxSitePatch(FSiteStruct Site);
 	UFUNCTION(BlueprintCallable)
 		void OnNetboxSitePatchResponse(FString ResponseContentString,
-			bool bWasSuccessful);
+									   bool bWasSuccessful);
+
+	UFUNCTION(BlueprintCallable)
+		void RequestNetboxDevicesGet();
+	UFUNCTION(BlueprintCallable)
+		void OnNetboxDevicesResponse(FString ResponseContentString,
+									 bool bWasSuccessful);
 
 	UFUNCTION(BlueprintCallable)
 		void ParseNetboxDeviceData(FNetboxDeviceResponse NetboxResponse);
@@ -154,7 +167,7 @@ public:
 		void RequestNetboxDevicesPost();
 	UFUNCTION(BlueprintCallable)
 		void OnNetboxPostDeviceResponse(FString ResponseContentString,
-			bool bWasSuccessful);
+										bool bWasSuccessful);
 
 	UFUNCTION(BlueprintCallable)
 		void RequestNetboxDevicesPatch();
@@ -162,7 +175,7 @@ public:
 		void RequestNetboxDevicePatch(UDevice* Device);
 	UFUNCTION(BlueprintCallable)
 		void OnNetboxPatchDeviceResponse(FString ResponseContentString,
-			bool bWasSuccessful);
+										 bool bWasSuccessful);
 
 	UFUNCTION(BlueprintCallable)
 		bool IsValidLatLong(float Latitude, float Longitude);
-- 
GitLab