From a0c5ced77f15d2ece4abeec90fb8406d99dd762c Mon Sep 17 00:00:00 2001 From: Frederik Martini Date: Thu, 13 Mar 2025 12:41:13 +0100 Subject: [PATCH 1/6] add config --- .gitignore | 3 +- README.md | 12 +++++++ internal/config/config.go | 15 ++++++++ internal/drawio/drawio.go | 20 +++++++++-- .../handlers/network_interface/handler.go | 4 +-- internal/drawio/handlers/subnet/handler.go | 35 ++++++++----------- internal/marshall/marshall.go | 17 +++++---- internal/providers/azure/provider.go | 4 +-- main.go | 5 +-- 9 files changed, 77 insertions(+), 38 deletions(-) create mode 100644 internal/config/config.go diff --git a/.gitignore b/.gitignore index 1b054aa..7365bc0 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ *.json *.exe !example/example.json -!example/example.drawio \ No newline at end of file +!example/example.drawio +.cloudsketch \ No newline at end of file diff --git a/README.md b/README.md index 66a3303..005f4cc 100644 --- a/README.md +++ b/README.md @@ -9,3 +9,15 @@ Ensure the executable has been added to your PATH, and run it with the ID of the ```terminal cloudsketch ``` + +## Filtering unwanted resource + +To remove unwanted resources from the final diagram, it is possible to provide a configuration file that must be placed in the same directory as the Cloudsketch executable. This configuration file must be called `.cloudsketch.json` and should be structured as follows: + +```json +{ + "blacklist": [] +} +``` + +In the `blacklist` property it is possible to specify resources that should not be included in the final diagram. Accepted values can be found [here](https://github.com/fremartini/cloudsketch/blob/main/internal/drawio/types/types.go) diff --git a/internal/config/config.go b/internal/config/config.go new file mode 100644 index 0000000..91d290d --- /dev/null +++ b/internal/config/config.go @@ -0,0 +1,15 @@ +package config + +import "cloudsketch/internal/marshall" + +const ( + CONFIG_FILE = ".cloudsketch.json" +) + +type config struct { + Blacklist []string +} + +func Read() (*config, bool) { + return marshall.UnmarshalIfExists[config](CONFIG_FILE) +} diff --git a/internal/drawio/drawio.go b/internal/drawio/drawio.go index 2a28084..21cdb39 100644 --- a/internal/drawio/drawio.go +++ b/internal/drawio/drawio.go @@ -1,6 +1,7 @@ package drawio import ( + "cloudsketch/internal/config" "cloudsketch/internal/datastructures/build_graph" "cloudsketch/internal/datastructures/set" "cloudsketch/internal/drawio/handlers/app_service" @@ -113,7 +114,22 @@ func New() *drawio { return &drawio{} } +func removeBlacklistedEntries() { + config, ok := config.Read() + + if !ok { + return + } + + // remove entries on the blacklist + for _, blacklistedItem := range config.Blacklist { + delete(commands, blacklistedItem) + } +} + func (d *drawio) WriteDiagram(filename string, resources []*models.Resource) error { + removeBlacklistedEntries() + // at this point only the Azure resources are known - this function adds the corresponding DrawIO icons resource_map, err := populateResourceMap(resources) @@ -138,11 +154,11 @@ func (d *drawio) WriteDiagram(filename string, resources []*models.Resource) err // private endpoints and NICs are typically used as icons attached to other icons and should therefore be rendered in front // TODO: implement a better solution? allResourcesThatShouldGoInBack := list.Filter(allResources, func(n *node.ResourceAndNode) bool { - return n.Resource.Type != types.PRIVATE_ENDPOINT && n.Resource.Type != types.NETWORK_INTERFACE && n.Resource.Type != types.PUBLIC_IP_ADDRESS + return n.Resource.Type != types.PRIVATE_ENDPOINT && n.Resource.Type != types.NETWORK_INTERFACE && n.Resource.Type != types.PUBLIC_IP_ADDRESS && n.Resource.Type != types.NETWORK_SECURITY_GROUP }) allResourcesThatShouldGoInFront := list.Filter(allResources, func(n *node.ResourceAndNode) bool { - return n.Resource.Type == types.PRIVATE_ENDPOINT || n.Resource.Type == types.NETWORK_INTERFACE || n.Resource.Type == types.PUBLIC_IP_ADDRESS + return n.Resource.Type == types.PRIVATE_ENDPOINT || n.Resource.Type == types.NETWORK_INTERFACE || n.Resource.Type == types.PUBLIC_IP_ADDRESS || n.Resource.Type == types.NETWORK_SECURITY_GROUP }) allResources = append(allResourcesThatShouldGoInBack, allResourcesThatShouldGoInFront...) diff --git a/internal/drawio/handlers/network_interface/handler.go b/internal/drawio/handlers/network_interface/handler.go index de99807..1401b0b 100644 --- a/internal/drawio/handlers/network_interface/handler.go +++ b/internal/drawio/handlers/network_interface/handler.go @@ -35,10 +35,10 @@ func (*handler) MapResource(resource *models.Resource) *node.Node { } func (*handler) PostProcessIcon(nic *node.ResourceAndNode, resource_map *map[string]*node.ResourceAndNode) *node.Node { - attachedTo := (*resource_map)[nic.Resource.Properties["attachedTo"]] + attachedTo, ok := (*resource_map)[nic.Resource.Properties["attachedTo"]] // dont draw NICs if they are attached to a blacklisted resource - if attachedTo == nil || isBlacklistedResource(attachedTo.Resource.Type) { + if !ok || isBlacklistedResource(attachedTo.Resource.Type) { delete(*resource_map, nic.Resource.Id) return nil } diff --git a/internal/drawio/handlers/subnet/handler.go b/internal/drawio/handlers/subnet/handler.go index 82bc870..793ba4b 100644 --- a/internal/drawio/handlers/subnet/handler.go +++ b/internal/drawio/handlers/subnet/handler.go @@ -44,56 +44,51 @@ func (*handler) MapResource(resource *models.Resource) *node.Node { return node.NewIcon(IMAGE, name, &geometry, link) } -func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *map[string]*node.ResourceAndNode) *node.Node { - var tmp *node.Node = nil - - routeTables := list.Filter(resource.Resource.DependsOn, func(dependency string) bool { +func getResourcseOfType(resource *models.Resource, resource_map *map[string]*node.ResourceAndNode, typ string) []string { + return list.Filter(resource.DependsOn, func(dependency string) bool { r, ok := (*resource_map)[dependency] if !ok { return false } - return r.Resource.Type == types.ROUTE_TABLE + return r.Resource.Type == typ }) +} +func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *map[string]*node.ResourceAndNode) *node.Node { + var parentGroup *node.Node = nil + + routeTables := getResourcseOfType(resource.Resource, resource_map, types.ROUTE_TABLE) if len(routeTables) == 1 { routeTable := (*resource_map)[routeTables[0]] - tmp = node.SetIcon(resource.Node, routeTable.Node, node.TOP_LEFT) + parentGroup = node.SetIcon(resource.Node, routeTable.Node, node.TOP_LEFT) } - networkSecurityGroups := list.Filter(resource.Resource.DependsOn, func(dependency string) bool { - r, ok := (*resource_map)[dependency] - - if !ok { - return false - } - - return r.Resource.Type == types.NETWORK_SECURITY_GROUP - }) + networkSecurityGroups := getResourcseOfType(resource.Resource, resource_map, types.NETWORK_SECURITY_GROUP) if len(networkSecurityGroups) == 1 { networkSecurityGroup := (*resource_map)[networkSecurityGroups[0]] // other subnets might point to the same NSG. If they do, ignore the merging if snets := resourcesWithReferencesTo(resource_map, networkSecurityGroup.Resource.Id); snets != 1 { - return tmp + return parentGroup } - if tmp == nil { + if parentGroup == nil { // route table icon was not set return node.SetIcon(resource.Node, networkSecurityGroup.Node, node.TOP_RIGHT) } // route table icon was set - networkSecurityGroup.Node.SetProperty("parent", tmp.Id()) + networkSecurityGroup.Node.SetProperty("parent", parentGroup.Id()) node.ScaleDownAndSetIconRelativeTo(networkSecurityGroup.Node, resource.Node.GetParentOrThis(), node.TOP_RIGHT) - networkSecurityGroup.Node.ContainedIn = tmp + networkSecurityGroup.Node.ContainedIn = parentGroup networkSecurityGroup.Node.SetProperty("value", "") } - return tmp + return parentGroup } func resourcesWithReferencesTo(resource_map *map[string]*node.ResourceAndNode, resourceId string) int { diff --git a/internal/marshall/marshall.go b/internal/marshall/marshall.go index 32d9c26..9f49a19 100644 --- a/internal/marshall/marshall.go +++ b/internal/marshall/marshall.go @@ -1,25 +1,24 @@ package marshall import ( - "cloudsketch/internal/drawio/models" "encoding/json" "errors" "log" "os" ) -func UnmarshalIfExists(file string) ([]*models.Resource, bool) { +func UnmarshalIfExists[T any](file string) (*T, bool) { if !FileExists(file) { return nil, false } - resources, err := UnmarshallResources(file) + config, err := UnmarshallResources[T](file) if err != nil { panic(err) } - return resources, true + return config, true } func FileExists(file string) bool { @@ -28,7 +27,7 @@ func FileExists(file string) bool { return !errors.Is(err, os.ErrNotExist) } -func MarshallResources(file string, resources []*models.Resource) error { +func MarshallResources[T any](file string, resources T) error { bytes, err := json.MarshalIndent(resources, "", "\t") if err != nil { @@ -48,16 +47,16 @@ func MarshallResources(file string, resources []*models.Resource) error { return err } -func UnmarshallResources(file string) ([]*models.Resource, error) { +func UnmarshallResources[T any](file string) (*T, error) { bytes, err := os.ReadFile(file) if err != nil { log.Fatal(err) } - var resources []*models.Resource + var config *T - err = json.Unmarshal(bytes, &resources) + err = json.Unmarshal(bytes, &config) - return resources, err + return config, err } diff --git a/internal/providers/azure/provider.go b/internal/providers/azure/provider.go index 9c8f164..7e08204 100644 --- a/internal/providers/azure/provider.go +++ b/internal/providers/azure/provider.go @@ -85,12 +85,12 @@ func (h *azureProvider) FetchResources(subscriptionId string) ([]*domainModels.R filename := fmt.Sprintf("%s_%s", subscription.Name, subscription.Id) filenameWithSuffix := fmt.Sprintf("%s.json", filename) - cachedResources, ok := marshall.UnmarshalIfExists(filenameWithSuffix) + cachedResources, ok := marshall.UnmarshalIfExists[[]*domainModels.Resource](filenameWithSuffix) if ok { log.Printf("using existing file %s\n", filenameWithSuffix) - return cachedResources, filename, nil + return *cachedResources, filename, nil } allResources, err := resource_group.New().Handle(ctx) diff --git a/main.go b/main.go index 028f306..fa74420 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package main import ( "cloudsketch/internal/drawio" + "cloudsketch/internal/drawio/models" "cloudsketch/internal/marshall" "cloudsketch/internal/providers/azure" "context" @@ -51,7 +52,7 @@ func main() { log.Printf("using existing file %s\n", file) - resources, err := marshall.UnmarshallResources(file) + resources, err := marshall.UnmarshallResources[[]*models.Resource](file) if err != nil { return err @@ -59,7 +60,7 @@ func main() { outFile := strings.ReplaceAll(file, ".json", ".drawio") - return drawio.New().WriteDiagram(outFile, resources) + return drawio.New().WriteDiagram(outFile, *resources) } // otherwise treat it as a subscription id From 149abcaf39ff7ce255f63262f8f148bfbdd49865 Mon Sep 17 00:00:00 2001 From: Frederik Martini Date: Thu, 13 Mar 2025 12:42:45 +0100 Subject: [PATCH 2/6] generalize marshall --- internal/marshall/marshall.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/internal/marshall/marshall.go b/internal/marshall/marshall.go index 9f49a19..3a8bc90 100644 --- a/internal/marshall/marshall.go +++ b/internal/marshall/marshall.go @@ -12,13 +12,13 @@ func UnmarshalIfExists[T any](file string) (*T, bool) { return nil, false } - config, err := UnmarshallResources[T](file) + r, err := UnmarshallResources[T](file) if err != nil { panic(err) } - return config, true + return r, true } func FileExists(file string) bool { @@ -27,8 +27,8 @@ func FileExists(file string) bool { return !errors.Is(err, os.ErrNotExist) } -func MarshallResources[T any](file string, resources T) error { - bytes, err := json.MarshalIndent(resources, "", "\t") +func MarshallResources[T any](file string, r T) error { + bytes, err := json.MarshalIndent(r, "", "\t") if err != nil { log.Fatal(err) @@ -54,9 +54,9 @@ func UnmarshallResources[T any](file string) (*T, error) { log.Fatal(err) } - var config *T + var r *T - err = json.Unmarshal(bytes, &config) + err = json.Unmarshal(bytes, &r) - return config, err + return r, err } From af1d526258cff431df43e8ebcee91b6a2349197c Mon Sep 17 00:00:00 2001 From: Frederik Martini Date: Thu, 13 Mar 2025 13:41:15 +0100 Subject: [PATCH 3/6] add search_service; mlw; ai_services --- internal/drawio/drawio.go | 6 ++ .../drawio/handlers/ai_services/handler.go | 56 +++++++++++++++++++ .../machine_learning_workspace/handler.go | 56 +++++++++++++++++++ .../drawio/handlers/search_service/handler.go | 56 +++++++++++++++++++ internal/drawio/images/images.go | 3 + internal/drawio/types/types.go | 3 + internal/providers/azure/provider.go | 3 + internal/providers/azure/types/types.go | 3 + 8 files changed, 186 insertions(+) create mode 100644 internal/drawio/handlers/ai_services/handler.go create mode 100644 internal/drawio/handlers/machine_learning_workspace/handler.go create mode 100644 internal/drawio/handlers/search_service/handler.go diff --git a/internal/drawio/drawio.go b/internal/drawio/drawio.go index 21cdb39..c2cc5be 100644 --- a/internal/drawio/drawio.go +++ b/internal/drawio/drawio.go @@ -4,6 +4,7 @@ import ( "cloudsketch/internal/config" "cloudsketch/internal/datastructures/build_graph" "cloudsketch/internal/datastructures/set" + "cloudsketch/internal/drawio/handlers/ai_services" "cloudsketch/internal/drawio/handlers/app_service" "cloudsketch/internal/drawio/handlers/app_service_plan" "cloudsketch/internal/drawio/handlers/application_gateway" @@ -24,6 +25,7 @@ import ( "cloudsketch/internal/drawio/handlers/load_balancer_frontend" "cloudsketch/internal/drawio/handlers/log_analytics" "cloudsketch/internal/drawio/handlers/logic_app" + "cloudsketch/internal/drawio/handlers/machine_learning_workspace" "cloudsketch/internal/drawio/handlers/nat_gateway" "cloudsketch/internal/drawio/handlers/network_interface" "cloudsketch/internal/drawio/handlers/network_security_group" @@ -36,6 +38,7 @@ import ( "cloudsketch/internal/drawio/handlers/recovery_service_vault" "cloudsketch/internal/drawio/handlers/redis" "cloudsketch/internal/drawio/handlers/route_table" + "cloudsketch/internal/drawio/handlers/search_service" "cloudsketch/internal/drawio/handlers/signalr" "cloudsketch/internal/drawio/handlers/sql_database" "cloudsketch/internal/drawio/handlers/sql_server" @@ -64,6 +67,7 @@ type handler interface { var ( commands handleFuncMap = handleFuncMap{ + ai_services.TYPE: ai_services.New(), app_service.TYPE: app_service.New(), app_service_plan.TYPE: app_service_plan.New(), application_gateway.TYPE: application_gateway.New(), @@ -83,6 +87,7 @@ var ( load_balancer_frontend.TYPE: load_balancer_frontend.New(), log_analytics.TYPE: log_analytics.New(), logic_app.TYPE: logic_app.New(), + machine_learning_workspace.TYPE: machine_learning_workspace.New(), nat_gateway.TYPE: nat_gateway.New(), network_interface.TYPE: network_interface.New(), network_security_group.TYPE: network_security_group.New(), @@ -94,6 +99,7 @@ var ( recovery_service_vault.TYPE: recovery_service_vault.New(), redis.TYPE: redis.New(), route_table.TYPE: route_table.New(), + search_service.TYPE: search_service.New(), signalr.TYPE: signalr.New(), sql_database.TYPE: sql_database.New(), sql_server.TYPE: sql_server.New(), diff --git a/internal/drawio/handlers/ai_services/handler.go b/internal/drawio/handlers/ai_services/handler.go new file mode 100644 index 0000000..9a71534 --- /dev/null +++ b/internal/drawio/handlers/ai_services/handler.go @@ -0,0 +1,56 @@ +package ai_services + +import ( + "cloudsketch/internal/drawio/handlers/node" + "cloudsketch/internal/drawio/images" + "cloudsketch/internal/drawio/models" + "cloudsketch/internal/drawio/types" +) + +type handler struct{} + +const ( + TYPE = types.AI_SERVICES + IMAGE = images.AI_SERVICES + WIDTH = 64 + HEIGHT = 68 +) + +func New() *handler { + return &handler{} +} + +func (*handler) MapResource(resource *models.Resource) *node.Node { + geometry := node.Geometry{ + X: 0, + Y: 0, + Width: WIDTH, + Height: HEIGHT, + } + + link := resource.GetLinkOrDefault() + + return node.NewIcon(IMAGE, resource.Name, &geometry, link) +} + +func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *map[string]*node.ResourceAndNode) *node.Node { + return nil +} + +func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { + arrows := []*node.Arrow{} + + sourceId := (*resource_map)[source.Id].Node.Id() + + for _, target := range targets { + targetId := (*resource_map)[target.Id].Node.Id() + + arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) + } + + return arrows +} + +func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { + return []*node.Node{} +} diff --git a/internal/drawio/handlers/machine_learning_workspace/handler.go b/internal/drawio/handlers/machine_learning_workspace/handler.go new file mode 100644 index 0000000..0d56cfd --- /dev/null +++ b/internal/drawio/handlers/machine_learning_workspace/handler.go @@ -0,0 +1,56 @@ +package machine_learning_workspace + +import ( + "cloudsketch/internal/drawio/handlers/node" + "cloudsketch/internal/drawio/images" + "cloudsketch/internal/drawio/models" + "cloudsketch/internal/drawio/types" +) + +type handler struct{} + +const ( + TYPE = types.MACHINE_LEARNING_WORKSPACE + IMAGE = images.MACHINE_LEARNING_WORKSPACE + WIDTH = 64 + HEIGHT = 68 +) + +func New() *handler { + return &handler{} +} + +func (*handler) MapResource(resource *models.Resource) *node.Node { + geometry := node.Geometry{ + X: 0, + Y: 0, + Width: WIDTH, + Height: HEIGHT, + } + + link := resource.GetLinkOrDefault() + + return node.NewIcon(IMAGE, resource.Name, &geometry, link) +} + +func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *map[string]*node.ResourceAndNode) *node.Node { + return nil +} + +func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { + arrows := []*node.Arrow{} + + sourceId := (*resource_map)[source.Id].Node.Id() + + for _, target := range targets { + targetId := (*resource_map)[target.Id].Node.Id() + + arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) + } + + return arrows +} + +func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { + return []*node.Node{} +} diff --git a/internal/drawio/handlers/search_service/handler.go b/internal/drawio/handlers/search_service/handler.go new file mode 100644 index 0000000..e40370b --- /dev/null +++ b/internal/drawio/handlers/search_service/handler.go @@ -0,0 +1,56 @@ +package search_service + +import ( + "cloudsketch/internal/drawio/handlers/node" + "cloudsketch/internal/drawio/images" + "cloudsketch/internal/drawio/models" + "cloudsketch/internal/drawio/types" +) + +type handler struct{} + +const ( + TYPE = types.SEARCH_SERVICE + IMAGE = images.SEARCH_SERVICE + WIDTH = 72 + HEIGHT = 52 +) + +func New() *handler { + return &handler{} +} + +func (*handler) MapResource(resource *models.Resource) *node.Node { + geometry := node.Geometry{ + X: 0, + Y: 0, + Width: WIDTH, + Height: HEIGHT, + } + + link := resource.GetLinkOrDefault() + + return node.NewIcon(IMAGE, resource.Name, &geometry, link) +} + +func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *map[string]*node.ResourceAndNode) *node.Node { + return nil +} + +func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { + arrows := []*node.Arrow{} + + sourceId := (*resource_map)[source.Id].Node.Id() + + for _, target := range targets { + targetId := (*resource_map)[target.Id].Node.Id() + + arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) + } + + return arrows +} + +func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { + return []*node.Node{} +} diff --git a/internal/drawio/images/images.go b/internal/drawio/images/images.go index 9b56fef..8f04268 100644 --- a/internal/drawio/images/images.go +++ b/internal/drawio/images/images.go @@ -1,6 +1,7 @@ package images const ( + AI_SERVICES = "img/lib/azure2/ai_machine_learning/AI_Studio.svg" APP_SERVICE = "img/lib/azure2/app_services/App_Services.svg" APP_SERVICE_PLAN = "img/lib/azure2/app_services/App_Service_Plans.svg" APPLICATION_GATEWAY = "img/lib/azure2/networking/Application_Gateways.svg" @@ -19,6 +20,7 @@ const ( LOAD_BALANCER_FRONTEND = PUBLIC_IP_ADDRESS LOG_ANALYTICS = "img/lib/azure2/management_governance/Log_Analytics_Workspaces.svg" LOGIC_APP = "img/lib/azure2/integration/Logic_Apps.svg" + MACHINE_LEARNING_WORKSPACE = "img/lib/azure2/ai_machine_learning/Machine_Learning.svg" NAT_GATEWAY = "img/lib/azure2/networking/NAT.svg" NETWORK_INTERFACE = "img/lib/azure2/networking/Network_Interfaces.svg" NETWORK_SECURITY_GROUP = "img/lib/azure2/networking/Network_Security_Groups.svg" @@ -29,6 +31,7 @@ const ( PUBLIC_IP_ADDRESS = "img/lib/azure2/networking/Public_IP_Addresses.svg" RECOVERY_SERVICE_VAULT = "img/lib/azure2/storage/Recovery_Services_Vaults.svg" REDIS = "img/lib/azure2/databases/Cache_Redis.svg" + SEARCH_SERVICE = "img/lib/azure2/app_services/Search_Services.svg" SIGNALR = "img/lib/azure2/web/SignalR.svg" SUBSCRIPTION = "img/lib/azure2/general/Subscriptions.svg" SQL_DATABASE = "img/lib/azure2/databases/SQL_Database.svg" diff --git a/internal/drawio/types/types.go b/internal/drawio/types/types.go index 4304777..0c32b65 100644 --- a/internal/drawio/types/types.go +++ b/internal/drawio/types/types.go @@ -1,6 +1,7 @@ package types const ( + AI_SERVICES = "AI_SERVICES" APP_SERVICE = "APP_SERVICE" APP_SERVICE_PLAN = "APP_SERVICE_PLAN" APPLICATION_GATEWAY = "APPLICATION_GATEWAY" @@ -20,6 +21,7 @@ const ( LOAD_BALANCER_FRONTEND = "LOAD_BALANCER_FRONTEND" LOG_ANALYTICS = "LOG_ANALYTICS" LOGIC_APP = "LOGIC_APP" + MACHINE_LEARNING_WORKSPACE = "MACHINE_LEARNING_WORKSPACE" NAT_GATEWAY = "NAT_GATEWAY" NETWORK_INTERFACE = "NETWORK_INTERFACE" NETWORK_SECURITY_GROUP = "NETWORK_SECURITY_GROUP" @@ -32,6 +34,7 @@ const ( REDIS = "REDIS" SIGNALR = "SIGNALR" ROUTE_TABLE = "ROUTE_TABLE" + SEARCH_SERVICE = "SEARCH_SERVICE" SQL_DATABASE = "SQL_DATABASE" SQL_SERVER = "SQL_SERVER" STATIC_WEB_APP = "STATIC_WEB_APP" diff --git a/internal/providers/azure/provider.go b/internal/providers/azure/provider.go index 7e08204..d146bf2 100644 --- a/internal/providers/azure/provider.go +++ b/internal/providers/azure/provider.go @@ -179,6 +179,7 @@ func generateAzurePortalLink(resource *models.Resource, tenant string) string { func mapTypeToDomainType(azType string, seen_unhandled_types *set.Set[string]) string { domainTypes := map[string]string{ + types.AI_SERVICES: domainTypes.AI_SERVICES, types.APP_SERVICE: domainTypes.APP_SERVICE, types.APP_SERVICE_PLAN: domainTypes.APP_SERVICE_PLAN, types.APPLICATION_GATEWAY: domainTypes.APPLICATION_GATEWAY, @@ -198,6 +199,7 @@ func mapTypeToDomainType(azType string, seen_unhandled_types *set.Set[string]) s types.LOAD_BALANCER_FRONTEND: domainTypes.LOAD_BALANCER_FRONTEND, types.LOG_ANALYTICS: domainTypes.LOG_ANALYTICS, types.LOGIC_APP: domainTypes.LOGIC_APP, + types.MACHINE_LEARNING_WORKSPACE: domainTypes.MACHINE_LEARNING_WORKSPACE, types.NAT_GATEWAY: domainTypes.NAT_GATEWAY, types.NETWORK_INTERFACE: domainTypes.NETWORK_INTERFACE, types.NETWORK_SECURITY_GROUP: domainTypes.NETWORK_SECURITY_GROUP, @@ -209,6 +211,7 @@ func mapTypeToDomainType(azType string, seen_unhandled_types *set.Set[string]) s types.RECOVERY_SERVICE_VAULT: domainTypes.RECOVERY_SERVICE_VAULT, types.REDIS: domainTypes.REDIS, types.ROUTE_TABLE: domainTypes.ROUTE_TABLE, + types.SEARCH_SERVICE: domainTypes.SEARCH_SERVICE, types.SIGNALR: domainTypes.SIGNALR, types.SQL_DATABASE: domainTypes.SQL_DATABASE, types.SQL_SERVER: domainTypes.SQL_SERVER, diff --git a/internal/providers/azure/types/types.go b/internal/providers/azure/types/types.go index c72661c..61ac0b3 100644 --- a/internal/providers/azure/types/types.go +++ b/internal/providers/azure/types/types.go @@ -1,6 +1,7 @@ package types const ( + AI_SERVICES = "Microsoft.CognitiveServices/accounts" APP_SERVICE = "Cloudsketch/appservice" APP_SERVICE_PLAN = "Microsoft.Web/serverFarms" APPLICATION_GATEWAY = "Microsoft.Network/applicationGateways" @@ -20,6 +21,7 @@ const ( LOAD_BALANCER_FRONTEND = "Microsoft.Network/loadBalancers/frontendIPConfigurations" LOG_ANALYTICS = "Microsoft.OperationalInsights/workspaces" LOGIC_APP = "Cloudsketch/logicapp" + MACHINE_LEARNING_WORKSPACE = "Microsoft.MachineLearningServices/workspaces" NAT_GATEWAY = "Microsoft.Network/natGateways" NETWORK_INTERFACE = "Microsoft.Network/networkInterfaces" NETWORK_SECURITY_GROUP = "Microsoft.Network/networkSecurityGroups" @@ -31,6 +33,7 @@ const ( RECOVERY_SERVICE_VAULT = "Microsoft.RecoveryServices/vaults" REDIS = "Microsoft.Cache/Redis" ROUTE_TABLE = "Microsoft.Network/routeTables" + SEARCH_SERVICE = "Microsoft.Search/searchServices" SIGNALR = "Microsoft.SignalRService/SignalR" SQL_DATABASE = "Microsoft.Sql/servers/databases" SQL_SERVER = "Microsoft.Sql/servers" From 74926373f1858643e9377e6745d223743f24876e Mon Sep 17 00:00:00 2001 From: Frederik Martini Date: Fri, 14 Mar 2025 10:32:39 +0100 Subject: [PATCH 4/6] move dns zone into vnet --- internal/drawio/drawio.go | 19 +++----- .../handlers/private_dns_zone/handler.go | 24 ++++++---- .../handlers/virtual_network/handler.go | 8 +--- internal/list/list.go | 10 +++++ .../handlers/private_dns_zone/handler.go | 44 +++++++++++++++---- 5 files changed, 70 insertions(+), 35 deletions(-) diff --git a/internal/drawio/drawio.go b/internal/drawio/drawio.go index c2cc5be..c4c6f1c 100644 --- a/internal/drawio/drawio.go +++ b/internal/drawio/drawio.go @@ -120,7 +120,7 @@ func New() *drawio { return &drawio{} } -func removeBlacklistedEntries() { +func removeBlacklistedHandlers() { config, ok := config.Read() if !ok { @@ -134,7 +134,7 @@ func removeBlacklistedEntries() { } func (d *drawio) WriteDiagram(filename string, resources []*models.Resource) error { - removeBlacklistedEntries() + removeBlacklistedHandlers() // at this point only the Azure resources are known - this function adds the corresponding DrawIO icons resource_map, err := populateResourceMap(resources) @@ -157,13 +157,8 @@ func (d *drawio) WriteDiagram(filename string, resources []*models.Resource) err allResources = append(allResources, resource) } - // private endpoints and NICs are typically used as icons attached to other icons and should therefore be rendered in front - // TODO: implement a better solution? - allResourcesThatShouldGoInBack := list.Filter(allResources, func(n *node.ResourceAndNode) bool { - return n.Resource.Type != types.PRIVATE_ENDPOINT && n.Resource.Type != types.NETWORK_INTERFACE && n.Resource.Type != types.PUBLIC_IP_ADDRESS && n.Resource.Type != types.NETWORK_SECURITY_GROUP - }) - - allResourcesThatShouldGoInFront := list.Filter(allResources, func(n *node.ResourceAndNode) bool { + // private endpoints, NICs, PIPs and NSGs are typically used as icons attached to other icons and should therefore be rendered in front of them + allResourcesThatShouldGoInFront, allResourcesThatShouldGoInBack := list.GroupBy(allResources, func(n *node.ResourceAndNode) bool { return n.Resource.Type == types.PRIVATE_ENDPOINT || n.Resource.Type == types.NETWORK_INTERFACE || n.Resource.Type == types.PUBLIC_IP_ADDRESS || n.Resource.Type == types.NETWORK_SECURITY_GROUP }) @@ -318,8 +313,8 @@ func addBoxes(resource_map *map[string]*node.ResourceAndNode) []*node.Node { }) // virtual netwoks and subnets needs to be handled last since they "depend" on all other resources - subnets := DrawGroupForResourceType(resources, types.SUBNET, resource_map) - vnets := DrawGroupForResourceType(resources, types.VIRTUAL_NETWORK, resource_map) + subnets := drawGroupForResourceType(resources, types.SUBNET, resource_map) + vnets := drawGroupForResourceType(resources, types.VIRTUAL_NETWORK, resource_map) // return vnets first so they are rendered in the background nodes := append(vnets, append(subnets, boxes...)...) @@ -327,7 +322,7 @@ func addBoxes(resource_map *map[string]*node.ResourceAndNode) []*node.Node { return nodes } -func DrawGroupForResourceType(resources []*models.Resource, typ string, resource_map *map[string]*node.ResourceAndNode) []*node.Node { +func drawGroupForResourceType(resources []*models.Resource, typ string, resource_map *map[string]*node.ResourceAndNode) []*node.Node { nodes := []*node.Node{} resourcesWithType := list.Filter(resources, func(r *models.Resource) bool { diff --git a/internal/drawio/handlers/private_dns_zone/handler.go b/internal/drawio/handlers/private_dns_zone/handler.go index 7a153fa..1a264a0 100644 --- a/internal/drawio/handlers/private_dns_zone/handler.go +++ b/internal/drawio/handlers/private_dns_zone/handler.go @@ -46,22 +46,32 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { arrows := []*node.Arrow{} - sourceId := (*resource_map)[source.Id].Node.Id() + sourceNode := (*resource_map)[source.Id].Node for _, target := range targets { - targetId := (*resource_map)[target.Id].Node.Id() - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) + targetNode := (*resource_map)[target.Id].Node + + // if they are in the same group, don't draw the arrow + if sourceNode.ContainedIn != nil && targetNode.ContainedIn != nil { + if sourceNode.GetParentOrThis() == targetNode.GetParentOrThis() { + continue + } + } + + arrows = append(arrows, node.NewArrow(sourceNode.Id(), targetNode.Id(), nil)) } return arrows } func (*handler) GroupResources(privateDNSZone *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { - nodes := []*node.Node{} - resourcesInPrivateDNSZone := getResourcesInPrivateDNSZone(resources, privateDNSZone.Id, resource_map) + if len(resourcesInPrivateDNSZone) == 0 { + return []*node.Node{} + } + privateDNSZoneNode := (*resource_map)[privateDNSZone.Id].Node privateDNSZoneNodeGeometry := privateDNSZoneNode.GetGeometry() @@ -85,9 +95,7 @@ func (*handler) GroupResources(privateDNSZone *models.Resource, resources []*mod node.ScaleDownAndSetIconRelativeTo(privateDNSZoneNode, box, node.BOTTOM_LEFT) - nodes = append(nodes, box) - - return nodes + return []*node.Node{box} } func getResourcesInPrivateDNSZone(resources []*models.Resource, adfId string, resource_map *map[string]*node.ResourceAndNode) []*node.ResourceAndNode { diff --git a/internal/drawio/handlers/virtual_network/handler.go b/internal/drawio/handlers/virtual_network/handler.go index 8ebf793..efb71f9 100644 --- a/internal/drawio/handlers/virtual_network/handler.go +++ b/internal/drawio/handlers/virtual_network/handler.go @@ -57,7 +57,7 @@ func (*handler) DrawDependency(source *models.Resource, targets []*models.Resour } func (*handler) GroupResources(vnet *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { - subnets := getAllSubnetsInVnet(vnet.Id, resources, resource_map) + subnets := getAllSResourcesInVnet(vnet.Id, resources, resource_map) vnetNode := (*resource_map)[vnet.Id].Node vnetNodegeometry := vnetNode.GetGeometry() @@ -78,12 +78,8 @@ func (*handler) GroupResources(vnet *models.Resource, resources []*models.Resour return []*node.Node{box} } -func getAllSubnetsInVnet(vnetId string, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { +func getAllSResourcesInVnet(vnetId string, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { subnets := list.Filter(resources, func(r *models.Resource) bool { - if r.Type != types.SUBNET { - return false - } - return list.Contains(r.DependsOn, func(dependency string) bool { return dependency == vnetId }) diff --git a/internal/list/list.go b/internal/list/list.go index fe7bd74..308b75b 100644 --- a/internal/list/list.go +++ b/internal/list/list.go @@ -63,3 +63,13 @@ func Fold[T, K any](v []T, acc K, f func(T, K) K) K { } return acc } + +func GroupBy[T any](v []T, f func(T) bool) ([]T, []T) { + bucketA := Filter(v, f) + + bucketB := Filter(v, func(e T) bool { + return !f(e) + }) + + return bucketA, bucketB +} diff --git a/internal/providers/azure/handlers/private_dns_zone/handler.go b/internal/providers/azure/handlers/private_dns_zone/handler.go index cd382c2..ef3e65d 100644 --- a/internal/providers/azure/handlers/private_dns_zone/handler.go +++ b/internal/providers/azure/handlers/private_dns_zone/handler.go @@ -23,24 +23,22 @@ func (h *handler) Handle(ctx *azContext.Context) ([]*models.Resource, error) { return nil, err } - client := clientFactory.NewPrivateZonesClient() - - dns_zone, err := client.Get(context.Background(), ctx.ResourceGroupName, ctx.ResourceName, nil) + dnsZone, err := clientFactory.NewPrivateZonesClient().Get(context.Background(), ctx.ResourceGroupName, ctx.ResourceName, nil) if err != nil { return nil, err } resource := &models.Resource{ - Id: *dns_zone.ID, - Name: *dns_zone.Name, - Type: *dns_zone.Type, + Id: *dnsZone.ID, + Name: *dnsZone.Name, + Type: *dnsZone.Type, DependsOn: []string{}, } resources := []*models.Resource{resource} - records, err := getRecordSet(clientFactory, ctx, dns_zone.ID) + records, err := getRecordSet(clientFactory, ctx, *dnsZone.ID) if err != nil { return nil, err @@ -48,10 +46,38 @@ func (h *handler) Handle(ctx *azContext.Context) ([]*models.Resource, error) { resources = append(resources, records...) + vnetLinks, err := getVnetLinks(clientFactory, ctx, *dnsZone.Name) + + if err != nil { + return nil, err + } + + resource.DependsOn = append(resource.DependsOn, vnetLinks...) + return resources, nil } -func getRecordSet(clientFactory *armprivatedns.ClientFactory, ctx *azContext.Context, dnsZoneId *string) ([]*models.Resource, error) { +func getVnetLinks(clientFactory *armprivatedns.ClientFactory, ctx *azContext.Context, dnsZoneName string) ([]string, error) { + pager := clientFactory.NewVirtualNetworkLinksClient().NewListPager(ctx.ResourceGroupName, dnsZoneName, nil) + + var links []*armprivatedns.VirtualNetworkLink + for pager.More() { + resp, err := pager.NextPage(context.Background()) + if err != nil { + return nil, err + } + + if resp.VirtualNetworkLinkListResult.Value != nil { + links = append(links, resp.VirtualNetworkLinkListResult.Value...) + } + } + + return list.Map(links, func(l *armprivatedns.VirtualNetworkLink) string { + return *l.Properties.VirtualNetwork.ID + }), nil +} + +func getRecordSet(clientFactory *armprivatedns.ClientFactory, ctx *azContext.Context, dnsZoneId string) ([]*models.Resource, error) { client := clientFactory.NewRecordSetsClient() pager := client.NewListPager(ctx.ResourceGroupName, ctx.ResourceName, nil) @@ -73,7 +99,7 @@ func getRecordSet(clientFactory *armprivatedns.ClientFactory, ctx *azContext.Con Id: *record.ID, Name: *record.Name, Type: types.DNS_RECORD, - DependsOn: []string{*dnsZoneId}, + DependsOn: []string{dnsZoneId}, } }) From 45be3893a2084298189771ebe3d43e1e8282514c Mon Sep 17 00:00:00 2001 From: Frederik Martini Date: Fri, 14 Mar 2025 11:32:36 +0100 Subject: [PATCH 5/6] refactor DrawDependency --- .../drawio/handlers/ai_services/handler.go | 12 +------- .../drawio/handlers/app_service/handler.go | 24 +--------------- .../handlers/app_service_plan/handler.go | 18 ++---------- .../handlers/application_gateway/handler.go | 23 +-------------- .../handlers/application_insights/handler.go | 12 +------- .../application_security_group/handler.go | 13 +-------- internal/drawio/handlers/bastion/handler.go | 22 +-------------- .../handlers/container_registry/handler.go | 12 +------- internal/drawio/handlers/cosmos/handler.go | 12 +------- .../drawio/handlers/data_factory/handler.go | 12 +------- .../handler.go | 17 +---------- .../handler.go | 18 +----------- .../handlers/databricks_workspace/handler.go | 12 +------- .../drawio/handlers/dns_record/handler.go | 17 +---------- .../drawio/handlers/function_app/handler.go | 24 ++-------------- internal/drawio/handlers/key_vault/handler.go | 12 +------- .../drawio/handlers/load_balancer/handler.go | 12 +------- .../load_balancer_frontend/handler.go | 17 +---------- .../drawio/handlers/log_analytics/handler.go | 12 +------- internal/drawio/handlers/logic_app/handler.go | 24 ++-------------- .../machine_learning_workspace/handler.go | 12 +------- .../drawio/handlers/nat_gateway/handler.go | 22 +-------------- .../handlers/network_interface/handler.go | 17 +---------- .../network_security_group/handler.go | 12 +------- internal/drawio/handlers/node/common.go | 28 +++++++++++++++++++ .../handlers/postgres_sql_server/handler.go | 12 +------- .../handlers/private_dns_zone/handler.go | 20 +------------ .../handlers/private_endpoint/handler.go | 24 +--------------- .../handlers/private_link_service/handler.go | 12 +------- .../handlers/public_ip_address/handler.go | 12 +------- .../recovery_service_vault/handler.go | 12 +------- internal/drawio/handlers/redis/handler.go | 12 +------- .../drawio/handlers/route_table/handler.go | 2 +- .../drawio/handlers/search_service/handler.go | 12 +------- internal/drawio/handlers/signalr/handler.go | 12 +------- .../drawio/handlers/sql_database/handler.go | 12 +------- .../drawio/handlers/sql_server/handler.go | 12 +------- .../drawio/handlers/static_web_app/handler.go | 12 +------- .../handlers/storage_account/handler.go | 12 +------- internal/drawio/handlers/subnet/handler.go | 24 +--------------- .../drawio/handlers/subscription/handler.go | 2 +- .../handlers/virtual_machine/handler.go | 20 +------------ .../virtual_machine_scale_set/handler.go | 17 +---------- .../handlers/virtual_network/handler.go | 6 ++-- 44 files changed, 78 insertions(+), 585 deletions(-) diff --git a/internal/drawio/handlers/ai_services/handler.go b/internal/drawio/handlers/ai_services/handler.go index 9a71534..1ff5020 100644 --- a/internal/drawio/handlers/ai_services/handler.go +++ b/internal/drawio/handlers/ai_services/handler.go @@ -38,17 +38,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/app_service/handler.go b/internal/drawio/handlers/app_service/handler.go index c86a078..237d773 100644 --- a/internal/drawio/handlers/app_service/handler.go +++ b/internal/drawio/handlers/app_service/handler.go @@ -38,29 +38,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceNode := (*resource_map)[source.Id].Node - - for _, target := range targets { - // don't draw arrows to subnets - if target.Type == types.SUBNET { - continue - } - - targetNode := (*resource_map)[target.Id].Node - - // if they are in the same group, don't draw the arrow - if sourceNode.ContainedIn != nil && targetNode.ContainedIn != nil { - if sourceNode.GetParentOrThis() == targetNode.GetParentOrThis() { - continue - } - } - - arrows = append(arrows, node.NewArrow(sourceNode.Id(), targetNode.Id(), nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{types.SUBNET}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/app_service_plan/handler.go b/internal/drawio/handlers/app_service_plan/handler.go index 2998351..d96e524 100644 --- a/internal/drawio/handlers/app_service_plan/handler.go +++ b/internal/drawio/handlers/app_service_plan/handler.go @@ -45,22 +45,8 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - // app service plans have an implicit dependency to a subnet. Don't draw these - if target.Type == types.SUBNET { - continue - } - - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + // app service plans have an implicit dependency to a subnet. Don't draw these + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{types.SUBNET}) } func (*handler) GroupResources(appServicePlan *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/application_gateway/handler.go b/internal/drawio/handlers/application_gateway/handler.go index 4a3001f..e605a48 100644 --- a/internal/drawio/handlers/application_gateway/handler.go +++ b/internal/drawio/handlers/application_gateway/handler.go @@ -54,28 +54,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - // don't draw arrows to subnets - if target.Type == types.SUBNET { - continue - } - - // don't draw arrows to public ips - if target.Type == types.PUBLIC_IP_ADDRESS { - continue - } - - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows - + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{types.SUBNET, types.PUBLIC_IP_ADDRESS}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/application_insights/handler.go b/internal/drawio/handlers/application_insights/handler.go index 52a503d..9cfb020 100644 --- a/internal/drawio/handlers/application_insights/handler.go +++ b/internal/drawio/handlers/application_insights/handler.go @@ -38,17 +38,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/application_security_group/handler.go b/internal/drawio/handlers/application_security_group/handler.go index d427033..d7438cd 100644 --- a/internal/drawio/handlers/application_security_group/handler.go +++ b/internal/drawio/handlers/application_security_group/handler.go @@ -38,18 +38,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/bastion/handler.go b/internal/drawio/handlers/bastion/handler.go index 42379a4..5aa14a9 100644 --- a/internal/drawio/handlers/bastion/handler.go +++ b/internal/drawio/handlers/bastion/handler.go @@ -54,27 +54,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - // don't draw arrows to subnets - if target.Type == types.SUBNET { - continue - } - - // don't draw arrows to public ips - if target.Type == types.PUBLIC_IP_ADDRESS { - continue - } - - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{types.SUBNET, types.PUBLIC_IP_ADDRESS}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/container_registry/handler.go b/internal/drawio/handlers/container_registry/handler.go index 41c8172..c5ee97b 100644 --- a/internal/drawio/handlers/container_registry/handler.go +++ b/internal/drawio/handlers/container_registry/handler.go @@ -39,17 +39,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/cosmos/handler.go b/internal/drawio/handlers/cosmos/handler.go index 2df39b0..db35957 100644 --- a/internal/drawio/handlers/cosmos/handler.go +++ b/internal/drawio/handlers/cosmos/handler.go @@ -38,17 +38,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/data_factory/handler.go b/internal/drawio/handlers/data_factory/handler.go index 01c2298..a3223f2 100644 --- a/internal/drawio/handlers/data_factory/handler.go +++ b/internal/drawio/handlers/data_factory/handler.go @@ -45,17 +45,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(dataFactory *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/data_factory_integration_runtime/handler.go b/internal/drawio/handlers/data_factory_integration_runtime/handler.go index f163d80..4dbd56b 100644 --- a/internal/drawio/handlers/data_factory_integration_runtime/handler.go +++ b/internal/drawio/handlers/data_factory_integration_runtime/handler.go @@ -39,22 +39,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceNode := (*resource_map)[source.Id].Node - - for _, target := range targets { - targetNode := (*resource_map)[target.Id].Node - - // ADF IR can be contained inside an ADF. Don't draw these - if sourceNode.ContainedIn == targetNode.ContainedIn { - continue - } - - arrows = append(arrows, node.NewArrow(sourceNode.Id(), targetNode.Id(), nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/data_factory_managed_private_endpoint/handler.go b/internal/drawio/handlers/data_factory_managed_private_endpoint/handler.go index 45ec120..61ae519 100644 --- a/internal/drawio/handlers/data_factory_managed_private_endpoint/handler.go +++ b/internal/drawio/handlers/data_factory_managed_private_endpoint/handler.go @@ -39,23 +39,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceNode := (*resource_map)[source.Id].Node - - for _, target := range targets { - targetNode := (*resource_map)[target.Id].Node - - // ADF MPE can be contained inside an ADF. Don't draw these - if sourceNode.ContainedIn == targetNode.ContainedIn { - continue - } - - arrows = append(arrows, node.NewArrow(sourceNode.Id(), targetNode.Id(), nil)) - } - - return arrows - + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/databricks_workspace/handler.go b/internal/drawio/handlers/databricks_workspace/handler.go index 93957cb..f0f1bbb 100644 --- a/internal/drawio/handlers/databricks_workspace/handler.go +++ b/internal/drawio/handlers/databricks_workspace/handler.go @@ -38,17 +38,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/dns_record/handler.go b/internal/drawio/handlers/dns_record/handler.go index 47d6fcf..d4358db 100644 --- a/internal/drawio/handlers/dns_record/handler.go +++ b/internal/drawio/handlers/dns_record/handler.go @@ -37,22 +37,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceNode := (*resource_map)[source.Id].Node - - for _, target := range targets { - targetNode := (*resource_map)[target.Id].Node - - // dns records can be contained inside aprivate DNS Zone. Don't draw these - if sourceNode.ContainedIn == targetNode.ContainedIn { - continue - } - - arrows = append(arrows, node.NewArrow(sourceNode.Id(), targetNode.Id(), nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/function_app/handler.go b/internal/drawio/handlers/function_app/handler.go index 04dda9d..acb5fc4 100644 --- a/internal/drawio/handlers/function_app/handler.go +++ b/internal/drawio/handlers/function_app/handler.go @@ -40,27 +40,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceNode := (*resource_map)[source.Id].Node - - for _, target := range targets { - // don't draw arrows to subnets - if target.Type == types.SUBNET { - continue - } - - targetNode := (*resource_map)[target.Id].Node - - // if they are in the same group, don't draw the arrow - if sourceNode.ContainedIn != nil && targetNode.ContainedIn != nil { - if sourceNode.GetParentOrThis() == targetNode.GetParentOrThis() { - continue - } - } - - arrows = append(arrows, node.NewArrow(sourceNode.Id(), targetNode.Id(), nil)) - } + arrows := node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) // add a dependency to the associated storage account. // this property only contains the name of the storage account @@ -76,6 +56,8 @@ func (*handler) DrawDependency(source *models.Resource, targets []*models.Resour return ran.Resource.Type == types.STORAGE_ACCOUNT && strings.Contains(ran.Resource.Name, storageAccountName) }) + sourceNode := (*resource_map)[source.Id].Node + arrows = append(arrows, node.NewArrow(sourceNode.Id(), resources[0].Node.Id(), nil)) // add a dependency to the outbound subnet diff --git a/internal/drawio/handlers/key_vault/handler.go b/internal/drawio/handlers/key_vault/handler.go index e05a86c..b7863d4 100644 --- a/internal/drawio/handlers/key_vault/handler.go +++ b/internal/drawio/handlers/key_vault/handler.go @@ -38,17 +38,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/load_balancer/handler.go b/internal/drawio/handlers/load_balancer/handler.go index 12a8405..492c15f 100644 --- a/internal/drawio/handlers/load_balancer/handler.go +++ b/internal/drawio/handlers/load_balancer/handler.go @@ -38,17 +38,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/load_balancer_frontend/handler.go b/internal/drawio/handlers/load_balancer_frontend/handler.go index da2306d..7636247 100644 --- a/internal/drawio/handlers/load_balancer_frontend/handler.go +++ b/internal/drawio/handlers/load_balancer_frontend/handler.go @@ -38,22 +38,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - // don't draw arrows to subnets - if target.Type == types.SUBNET { - continue - } - - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{types.SUBNET}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/log_analytics/handler.go b/internal/drawio/handlers/log_analytics/handler.go index b5b9575..fa8712d 100644 --- a/internal/drawio/handlers/log_analytics/handler.go +++ b/internal/drawio/handlers/log_analytics/handler.go @@ -38,17 +38,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/logic_app/handler.go b/internal/drawio/handlers/logic_app/handler.go index e6a3b06..db341d0 100644 --- a/internal/drawio/handlers/logic_app/handler.go +++ b/internal/drawio/handlers/logic_app/handler.go @@ -38,33 +38,15 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceNode := (*resource_map)[source.Id].Node - - for _, target := range targets { - // don't draw arrows to subnets - if target.Type == types.SUBNET { - continue - } - - targetNode := (*resource_map)[target.Id].Node - - // if they are in the same group, don't draw the arrow - if sourceNode.ContainedIn != nil && targetNode.ContainedIn != nil { - if sourceNode.GetParentOrThis() == targetNode.GetParentOrThis() { - continue - } - } - - arrows = append(arrows, node.NewArrow(sourceNode.Id(), targetNode.Id(), nil)) - } + arrows := node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{types.SUBNET}) // add a dependency to the outbound subnet dashed := "dashed=1" outboundSubnet := source.Properties["outboundSubnet"] outboundSubnetNode := (*resource_map)[outboundSubnet].Node + + sourceNode := (*resource_map)[source.Id].Node arrows = append(arrows, node.NewArrow(sourceNode.Id(), outboundSubnetNode.Id(), &dashed)) return arrows diff --git a/internal/drawio/handlers/machine_learning_workspace/handler.go b/internal/drawio/handlers/machine_learning_workspace/handler.go index 0d56cfd..3a558da 100644 --- a/internal/drawio/handlers/machine_learning_workspace/handler.go +++ b/internal/drawio/handlers/machine_learning_workspace/handler.go @@ -38,17 +38,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{types.SUBNET}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/nat_gateway/handler.go b/internal/drawio/handlers/nat_gateway/handler.go index 3953961..735d617 100644 --- a/internal/drawio/handlers/nat_gateway/handler.go +++ b/internal/drawio/handlers/nat_gateway/handler.go @@ -54,27 +54,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - // don't draw arrows to subnets - if target.Type == types.SUBNET { - continue - } - - // don't draw arrows to public ips - if target.Type == types.PUBLIC_IP_ADDRESS { - continue - } - - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{types.SUBNET, types.PUBLIC_IP_ADDRESS}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/network_interface/handler.go b/internal/drawio/handlers/network_interface/handler.go index 1401b0b..60402d6 100644 --- a/internal/drawio/handlers/network_interface/handler.go +++ b/internal/drawio/handlers/network_interface/handler.go @@ -86,22 +86,7 @@ func getNICsPointingToResource(resource_map *map[string]*node.ResourceAndNode, a } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceNode := (*resource_map)[source.Id].Node - - for _, target := range targets { - // don't draw arrows to subnets - if target.Type == types.SUBNET { - continue - } - - targetNode := (*resource_map)[target.Id].Node - - arrows = append(arrows, node.NewArrow(sourceNode.Id(), targetNode.Id(), nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{types.SUBNET}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/network_security_group/handler.go b/internal/drawio/handlers/network_security_group/handler.go index 5c29c16..2fdf313 100644 --- a/internal/drawio/handlers/network_security_group/handler.go +++ b/internal/drawio/handlers/network_security_group/handler.go @@ -38,17 +38,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/node/common.go b/internal/drawio/handlers/node/common.go index aed6a9c..584409e 100644 --- a/internal/drawio/handlers/node/common.go +++ b/internal/drawio/handlers/node/common.go @@ -1,6 +1,7 @@ package node import ( + "cloudsketch/internal/drawio/models" "cloudsketch/internal/list" "log" "math" @@ -225,3 +226,30 @@ func fillResourcesInBoxSquare(box *Node, nodes []*Node, padding int) { boxGeometry.Height += nodes[len(nodes)-1].GetGeometry().Height + padding boxGeometry.Width += padding } + +func DrawDependencyArrowsToTarget(source *models.Resource, targets []*models.Resource, resource_map *map[string]*ResourceAndNode, typeBlacklist []string) []*Arrow { + arrows := []*Arrow{} + + sourceNode := (*resource_map)[source.Id].Node + + for _, target := range targets { + target := (*resource_map)[target.Id] + + if list.Contains(typeBlacklist, func(t string) bool { + return target.Resource.Type == t + }) { + continue + } + + // if they are in the same group, don't draw the arrow + if sourceNode.ContainedIn != nil && target.Node.ContainedIn != nil { + if sourceNode.GetParentOrThis() == target.Node.GetParentOrThis() { + continue + } + } + + arrows = append(arrows, NewArrow(sourceNode.Id(), target.Node.Id(), nil)) + } + + return arrows +} diff --git a/internal/drawio/handlers/postgres_sql_server/handler.go b/internal/drawio/handlers/postgres_sql_server/handler.go index 96e31c6..cdd2933 100644 --- a/internal/drawio/handlers/postgres_sql_server/handler.go +++ b/internal/drawio/handlers/postgres_sql_server/handler.go @@ -39,17 +39,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/private_dns_zone/handler.go b/internal/drawio/handlers/private_dns_zone/handler.go index 1a264a0..36aab72 100644 --- a/internal/drawio/handlers/private_dns_zone/handler.go +++ b/internal/drawio/handlers/private_dns_zone/handler.go @@ -44,25 +44,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceNode := (*resource_map)[source.Id].Node - - for _, target := range targets { - - targetNode := (*resource_map)[target.Id].Node - - // if they are in the same group, don't draw the arrow - if sourceNode.ContainedIn != nil && targetNode.ContainedIn != nil { - if sourceNode.GetParentOrThis() == targetNode.GetParentOrThis() { - continue - } - } - - arrows = append(arrows, node.NewArrow(sourceNode.Id(), targetNode.Id(), nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(privateDNSZone *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/private_endpoint/handler.go b/internal/drawio/handlers/private_endpoint/handler.go index 8cbd630..5d71652 100644 --- a/internal/drawio/handlers/private_endpoint/handler.go +++ b/internal/drawio/handlers/private_endpoint/handler.go @@ -147,29 +147,7 @@ func getPrivateEndpointPointingToResource(resource_map *map[string]*node.Resourc } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceNode := (*resource_map)[source.Id].Node - - for _, target := range targets { - // don't draw arrows to subnets - if target.Type == types.SUBNET { - continue - } - - targetNode := (*resource_map)[target.Id].Node - - // if they are in the same group, don't draw the arrow - if sourceNode.ContainedIn != nil && targetNode.ContainedIn != nil { - if sourceNode.ContainedIn == targetNode.ContainedIn { - continue - } - } - - arrows = append(arrows, node.NewArrow(sourceNode.Id(), targetNode.Id(), nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{types.SUBNET}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/private_link_service/handler.go b/internal/drawio/handlers/private_link_service/handler.go index f9f3482..2699961 100644 --- a/internal/drawio/handlers/private_link_service/handler.go +++ b/internal/drawio/handlers/private_link_service/handler.go @@ -38,17 +38,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/public_ip_address/handler.go b/internal/drawio/handlers/public_ip_address/handler.go index 0f2fd19..baa40ea 100644 --- a/internal/drawio/handlers/public_ip_address/handler.go +++ b/internal/drawio/handlers/public_ip_address/handler.go @@ -38,17 +38,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/recovery_service_vault/handler.go b/internal/drawio/handlers/recovery_service_vault/handler.go index 8ad3401..6018704 100644 --- a/internal/drawio/handlers/recovery_service_vault/handler.go +++ b/internal/drawio/handlers/recovery_service_vault/handler.go @@ -38,17 +38,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/redis/handler.go b/internal/drawio/handlers/redis/handler.go index 59a0708..02744ce 100644 --- a/internal/drawio/handlers/redis/handler.go +++ b/internal/drawio/handlers/redis/handler.go @@ -38,17 +38,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/route_table/handler.go b/internal/drawio/handlers/route_table/handler.go index d97b36e..c8e311a 100644 --- a/internal/drawio/handlers/route_table/handler.go +++ b/internal/drawio/handlers/route_table/handler.go @@ -41,7 +41,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - return []*node.Arrow{} + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/search_service/handler.go b/internal/drawio/handlers/search_service/handler.go index e40370b..1b635b5 100644 --- a/internal/drawio/handlers/search_service/handler.go +++ b/internal/drawio/handlers/search_service/handler.go @@ -38,17 +38,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/signalr/handler.go b/internal/drawio/handlers/signalr/handler.go index c16cea0..5ac88a9 100644 --- a/internal/drawio/handlers/signalr/handler.go +++ b/internal/drawio/handlers/signalr/handler.go @@ -38,17 +38,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/sql_database/handler.go b/internal/drawio/handlers/sql_database/handler.go index 5610984..214f89a 100644 --- a/internal/drawio/handlers/sql_database/handler.go +++ b/internal/drawio/handlers/sql_database/handler.go @@ -38,17 +38,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/sql_server/handler.go b/internal/drawio/handlers/sql_server/handler.go index da950e7..a925d2a 100644 --- a/internal/drawio/handlers/sql_server/handler.go +++ b/internal/drawio/handlers/sql_server/handler.go @@ -38,17 +38,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/static_web_app/handler.go b/internal/drawio/handlers/static_web_app/handler.go index 7a3a464..9980d77 100644 --- a/internal/drawio/handlers/static_web_app/handler.go +++ b/internal/drawio/handlers/static_web_app/handler.go @@ -38,17 +38,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/storage_account/handler.go b/internal/drawio/handlers/storage_account/handler.go index 2d94428..b464bdf 100644 --- a/internal/drawio/handlers/storage_account/handler.go +++ b/internal/drawio/handlers/storage_account/handler.go @@ -38,17 +38,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/subnet/handler.go b/internal/drawio/handlers/subnet/handler.go index 793ba4b..d9d8b3f 100644 --- a/internal/drawio/handlers/subnet/handler.go +++ b/internal/drawio/handlers/subnet/handler.go @@ -106,29 +106,7 @@ func resourcesWithReferencesTo(resource_map *map[string]*node.ResourceAndNode, r } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceNode := (*resource_map)[source.Id].Node - - for _, target := range targets { - // don't draw arrows to virtual networks - if target.Type == types.VIRTUAL_NETWORK { - continue - } - - targetNode := (*resource_map)[target.Id].Node - - // if they are in the same group, don't draw the arrow - if sourceNode.ContainedIn != nil && targetNode.ContainedIn != nil { - if sourceNode.ContainedIn == targetNode.ContainedIn { - continue - } - } - - arrows = append(arrows, node.NewArrow(sourceNode.Id(), targetNode.Id(), nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{types.VIRTUAL_NETWORK}) } func (*handler) GroupResources(subnet *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/subscription/handler.go b/internal/drawio/handlers/subscription/handler.go index cbae625..a614ddd 100644 --- a/internal/drawio/handlers/subscription/handler.go +++ b/internal/drawio/handlers/subscription/handler.go @@ -39,7 +39,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - return []*node.Arrow{} + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/virtual_machine/handler.go b/internal/drawio/handlers/virtual_machine/handler.go index 297a2be..e1c37ca 100644 --- a/internal/drawio/handlers/virtual_machine/handler.go +++ b/internal/drawio/handlers/virtual_machine/handler.go @@ -38,25 +38,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceNode := (*resource_map)[source.Id].Node - - for _, target := range targets { - - targetNode := (*resource_map)[target.Id].Node - - // if they are in the same group, don't draw the arrow - if sourceNode.ContainedIn != nil && targetNode.ContainedIn != nil { - if sourceNode.ContainedIn == targetNode.ContainedIn { - continue - } - } - - arrows = append(arrows, node.NewArrow(sourceNode.Id(), targetNode.Id(), nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/virtual_machine_scale_set/handler.go b/internal/drawio/handlers/virtual_machine_scale_set/handler.go index f17dad4..40f74f6 100644 --- a/internal/drawio/handlers/virtual_machine_scale_set/handler.go +++ b/internal/drawio/handlers/virtual_machine_scale_set/handler.go @@ -38,22 +38,7 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - arrows := []*node.Arrow{} - - sourceId := (*resource_map)[source.Id].Node.Id() - - for _, target := range targets { - // don't draw arrows to subnets - if target.Type == types.SUBNET { - continue - } - - targetId := (*resource_map)[target.Id].Node.Id() - - arrows = append(arrows, node.NewArrow(sourceId, targetId, nil)) - } - - return arrows + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(_ *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { diff --git a/internal/drawio/handlers/virtual_network/handler.go b/internal/drawio/handlers/virtual_network/handler.go index efb71f9..dfb1e6b 100644 --- a/internal/drawio/handlers/virtual_network/handler.go +++ b/internal/drawio/handlers/virtual_network/handler.go @@ -53,11 +53,11 @@ func (*handler) PostProcessIcon(resource *node.ResourceAndNode, resource_map *ma } func (*handler) DrawDependency(source *models.Resource, targets []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Arrow { - return []*node.Arrow{} + return node.DrawDependencyArrowsToTarget(source, targets, resource_map, []string{}) } func (*handler) GroupResources(vnet *models.Resource, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { - subnets := getAllSResourcesInVnet(vnet.Id, resources, resource_map) + subnets := getAllResourcesInVnet(vnet.Id, resources, resource_map) vnetNode := (*resource_map)[vnet.Id].Node vnetNodegeometry := vnetNode.GetGeometry() @@ -78,7 +78,7 @@ func (*handler) GroupResources(vnet *models.Resource, resources []*models.Resour return []*node.Node{box} } -func getAllSResourcesInVnet(vnetId string, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { +func getAllResourcesInVnet(vnetId string, resources []*models.Resource, resource_map *map[string]*node.ResourceAndNode) []*node.Node { subnets := list.Filter(resources, func(r *models.Resource) bool { return list.Contains(r.DependsOn, func(dependency string) bool { return dependency == vnetId From 441503d41105d3b24672596356ce7e7add5e696d Mon Sep 17 00:00:00 2001 From: Frederik Martini Date: Fri, 14 Mar 2025 12:57:21 +0100 Subject: [PATCH 6/6] refactor DrawDependencyArrowsToTarget --- internal/drawio/handlers/node/common.go | 36 ++++++++++++++----------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/internal/drawio/handlers/node/common.go b/internal/drawio/handlers/node/common.go index 584409e..8077c47 100644 --- a/internal/drawio/handlers/node/common.go +++ b/internal/drawio/handlers/node/common.go @@ -228,28 +228,34 @@ func fillResourcesInBoxSquare(box *Node, nodes []*Node, padding int) { } func DrawDependencyArrowsToTarget(source *models.Resource, targets []*models.Resource, resource_map *map[string]*ResourceAndNode, typeBlacklist []string) []*Arrow { - arrows := []*Arrow{} - sourceNode := (*resource_map)[source.Id].Node - for _, target := range targets { - target := (*resource_map)[target.Id] + targetResources := list.Map(targets, func(target *models.Resource) *ResourceAndNode { + return (*resource_map)[target.Id] + }) - if list.Contains(typeBlacklist, func(t string) bool { + // remove entries from the blacklist + targetResources = list.Filter(targetResources, func(target *ResourceAndNode) bool { + return !list.Contains(typeBlacklist, func(t string) bool { return target.Resource.Type == t - }) { - continue - } + }) + }) - // if they are in the same group, don't draw the arrow - if sourceNode.ContainedIn != nil && target.Node.ContainedIn != nil { - if sourceNode.GetParentOrThis() == target.Node.GetParentOrThis() { - continue - } + // remove entries that are in the same group + targetResources = list.Filter(targetResources, func(target *ResourceAndNode) bool { + + if sourceNode.ContainedIn == nil || target.Node.ContainedIn == nil { + return true } - arrows = append(arrows, NewArrow(sourceNode.Id(), target.Node.Id(), nil)) - } + hasSameGroup := sourceNode.GetParentOrThis() == target.Node.GetParentOrThis() + + return !hasSameGroup + }) + + arrows := list.Fold(targetResources, []*Arrow{}, func(target *ResourceAndNode, acc []*Arrow) []*Arrow { + return append(acc, NewArrow(sourceNode.Id(), target.Node.Id(), nil)) + }) return arrows }