Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

subnet-grouping2 #245

Merged
merged 27 commits into from
Jan 1, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
120b132
init
haim-kermany Nov 29, 2023
0d800b2
go 20
haim-kermany Nov 29, 2023
3b05954
go 20
haim-kermany Nov 29, 2023
e75c3c0
not 1.2
haim-kermany Nov 29, 2023
a120861
Merge branch 'main' into subnet-grouping2
haim-kermany Dec 7, 2023
4d6a3a2
ShowOnSubnetMode for tgw
haim-kermany Dec 7, 2023
55a6259
use go-version-file
haim-kermany Dec 7, 2023
f056052
CR from Ziv
haim-kermany Dec 7, 2023
6d2840c
removing subnetMode flag
haim-kermany Dec 7, 2023
0fd51e2
does not work
haim-kermany Dec 7, 2023
85e53ff
another try
haim-kermany Dec 7, 2023
4290fdf
change subnetmode Location
haim-kermany Dec 7, 2023
d911f9b
test
haim-kermany Dec 7, 2023
ee96ef4
lint
haim-kermany Dec 7, 2023
d609bb7
code review
haim-kermany Dec 7, 2023
7d9baac
documenting
haim-kermany Dec 7, 2023
95daa44
using maps from golang 21
haim-kermany Dec 10, 2023
16d6066
Merge branch 'main' into subnet-grouping2
haim-kermany Dec 12, 2023
ae50b61
code review
haim-kermany Dec 12, 2023
c47a06e
not use pointer to map
haim-kermany Dec 12, 2023
f85c7c8
handle pointers to string
haim-kermany Dec 12, 2023
e878c09
adding tests to main
haim-kermany Dec 18, 2023
2a0a03b
Merge branch 'main' into subnet-grouping2
haim-kermany Dec 18, 2023
9fa3846
Merge branch 'main' into subnet-grouping2
haim-kermany Dec 20, 2023
3db9e2b
Merge branch 'main' into subnet-grouping2
haim-kermany Dec 21, 2023
bf29ee0
Merge branch 'main' into subnet-grouping2
haim-kermany Dec 27, 2023
a1d301c
Merge branch 'main' into subnet-grouping2
haim-kermany Jan 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/go-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe
with:
go-version: 1.18
go-version-file: ./go.mod

- name: Build
env:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ jobs:
steps:
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe
with:
go-version: 1.18
go-version: "1.20"
zivnevo marked this conversation as resolved.
Show resolved Hide resolved
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- uses: golangci/golangci-lint-action@3a919529898de77ec3da873e3063ca4b10e7f5cc
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/np-guard/vpc-network-config-analyzer

go 1.18
go 1.20

require (
github.com/IBM/vpc-go-sdk v0.44.0
Expand Down
20 changes: 11 additions & 9 deletions pkg/drawio/abstractTreeNode.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@ const (
)

type abstractTreeNode struct {
id uint
x int
y int
name string
width int
height int
parent TreeNodeInterface
location *Location
id uint
x int
y int
name string
width int
height int
parent TreeNodeInterface
location *Location
doNotShowInDrawio bool
}

func (tn *abstractTreeNode) Label() string { return tn.name }
Expand Down Expand Up @@ -51,7 +52,8 @@ func (tn *abstractTreeNode) DrawioParent() TreeNodeInterface { return tn.parent

func (tn *abstractTreeNode) setLocation(location *Location) { tn.location = location }
func (tn *abstractTreeNode) setParent(p TreeNodeInterface) { tn.parent = p }
func (tn *abstractTreeNode) NotShownInDrawio() bool { return false }
func (tn *abstractTreeNode) NotShownInDrawio() bool { return tn.doNotShowInDrawio }
func (tn *abstractTreeNode) SetNotShownInDrawio() { tn.doNotShowInDrawio = true }

var idCounter uint = minID

Expand Down
11 changes: 8 additions & 3 deletions pkg/drawio/createMapFile.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,15 @@ func (data *drawioData) ElementComment(tn TreeNodeInterface) string {
// 2. we put the icons above the squares so we can mouse over it for tooltips
// 3. we put the sgs in the bottom. if a sg is above a square, it will block the the tooltip of the children of the square.
zivnevo marked this conversation as resolved.
Show resolved Hide resolved
func orderNodesForDrawio(nodes []TreeNodeInterface) []TreeNodeInterface {
var sg, sq, ln, ic, orderedNodes []TreeNodeInterface
var sg, sq, ln, ic, grs, orderedNodes []TreeNodeInterface
for _, tn := range nodes {
switch {
case reflect.TypeOf(tn).Elem() == reflect.TypeOf(PartialSGTreeNode{}):
sg = append(sg, tn)
case reflect.TypeOf(tn).Elem() == reflect.TypeOf(GroupSquareTreeNode{}):
grs = append(grs, tn)
case reflect.TypeOf(tn).Elem() == reflect.TypeOf(GroupSubnetsSquareTreeNode{}):
grs = append(grs, tn)
case tn.IsSquare():
sq = append(sq, tn)
case tn.IsIcon():
Expand All @@ -57,15 +61,16 @@ func orderNodesForDrawio(nodes []TreeNodeInterface) []TreeNodeInterface {
ln = append(ln, tn)
}
}
orderedNodes = append(orderedNodes, grs...)
orderedNodes = append(orderedNodes, sg...)
orderedNodes = append(orderedNodes, sq...)
orderedNodes = append(orderedNodes, ic...)
orderedNodes = append(orderedNodes, ln...)
return orderedNodes
}

func CreateDrawioConnectivityMapFile(network SquareTreeNodeInterface, outputFile string) error {
newLayout(network).layout()
func CreateDrawioConnectivityMapFile(network SquareTreeNodeInterface, outputFile string, subnetMode bool) error {
newLayout(network, subnetMode).layout()

return writeDrawioFile(NewDrawioData(network), outputFile)
}
Expand Down
69 changes: 64 additions & 5 deletions pkg/drawio/drawio_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,37 @@ import (

func TestWithParsing(t *testing.T) {
n := createNetwork()
err := CreateDrawioConnectivityMapFile(n, "fake.drawio")
err := CreateDrawioConnectivityMapFile(n, "fake.drawio", false)
if err != nil {
fmt.Println("Error when calling CreateDrawioConnectivityMapFile():", err)
}
n = createNetwork2()
err = CreateDrawioConnectivityMapFile(n, "fake2.drawio")
err = CreateDrawioConnectivityMapFile(n, "fake2.drawio", false)
if err != nil {
fmt.Println("Error when calling CreateDrawioConnectivityMapFile():", err)
}
n = createNetworkGrouping()
err = CreateDrawioConnectivityMapFile(n, "grouping.drawio")
err = CreateDrawioConnectivityMapFile(n, "grouping.drawio", false)
if err != nil {
fmt.Println("Error when calling CreateDrawioConnectivityMapFile():", err)
}
n = createNetworkSubnetGrouping()
err = CreateDrawioConnectivityMapFile(n, "subnetGrouping.drawio", true)
if err != nil {
fmt.Println("Error when calling CreateDrawioConnectivityMapFile():", err)
}

n2 := NewNetworkTreeNode()
NewCloudTreeNode(n2, "empty Cloud")
NewPublicNetworkTreeNode(n2)
NewCloudTreeNode(n2, "empty cloud2")
err = CreateDrawioConnectivityMapFile(n2, "fake3.drawio")
err = CreateDrawioConnectivityMapFile(n2, "fake3.drawio", false)
if err != nil {
fmt.Println("Error when calling CreateDrawioConnectivityMapFile():", err)
}

n = createNetworkAllTypes()
err = CreateDrawioConnectivityMapFile(n, "all.drawio")
err = CreateDrawioConnectivityMapFile(n, "all.drawio", false)
if err != nil {
fmt.Println("Error when calling CreateDrawioConnectivityMapFile():", err)
}
Expand Down Expand Up @@ -278,6 +284,59 @@ func createNetworkAllTypes() SquareTreeNodeInterface {
return network
}

func createZone(zones *[][]SquareTreeNodeInterface, vpc *VpcTreeNode, size int, name string) {
zone := NewZoneTreeNode(vpc, name)
subnets := make([]SquareTreeNodeInterface, size)
*zones = append(*zones, subnets)
for i := 0; i < size; i++ {
sname := fmt.Sprint(name, i)
subnets[i] = NewSubnetTreeNode(zone, sname, "", "")
}
}
func createGroup(zones *[][]SquareTreeNodeInterface, vpc *VpcTreeNode, i1, i2, j1, j2 int) SquareTreeNodeInterface {
gr := []SquareTreeNodeInterface{}
for i := i1; i <= i2; i++ {
for j := j1; j <= j2; j++ {
gr = append(gr, (*zones)[i][j])
}
}
g := GroupedSubnetsSquare(vpc, gr)
g.(*GroupSubnetsSquareTreeNode).name = fmt.Sprintf("%d-%d,%d,%d", i1, i2, j1, j2)
return g
}

func createNetworkSubnetGrouping() SquareTreeNodeInterface {
network := NewNetworkTreeNode()
zones := &[][]SquareTreeNodeInterface{}
cloud1 := NewCloudTreeNode(network, "IBM Cloud")
publicNetwork := NewPublicNetworkTreeNode(network)
vpc1 := NewVpcTreeNode(cloud1, "vpc1")
for i := 0; i < 10; i++ {
createZone(zones, vpc1, 8, fmt.Sprintf("z%d", i))
}
groups := []SquareTreeNodeInterface{
createGroup(zones, vpc1, 0, 0, 0, 1),
createGroup(zones, vpc1, 1, 1, 0, 1),
createGroup(zones, vpc1, 0, 2, 0, 6),
createGroup(zones, vpc1, 0, 2, 4, 6),
createGroup(zones, vpc1, 3, 3, 1, 2),
createGroup(zones, vpc1, 2, 3, 1, 2),
createGroup(zones, vpc1, 0, 4, 0, 3),
createGroup(zones, vpc1, 0, 5, 0, 3),

createGroup(zones, vpc1, 6, 7, 0, 1),
createGroup(zones, vpc1, 6, 6, 2, 3),
createGroup(zones, vpc1, 7, 8, 1, 2),
}
NewConnectivityLineTreeNode(network, groups[0], groups[len(groups)-1], true, "gconn")

for _, gr := range groups {
i1 := NewInternetTreeNode(publicNetwork, "I "+gr.Label())
NewConnectivityLineTreeNode(network, gr, i1, true, "gconn "+gr.Label())
}
return network
}

func createNetworkGrouping() SquareTreeNodeInterface {
network := NewNetworkTreeNode()
publicNetwork := NewPublicNetworkTreeNode(network)
Expand Down
123 changes: 117 additions & 6 deletions pkg/drawio/layout.go
zivnevo marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,24 @@ const (
)

type layoutS struct {
network SquareTreeNodeInterface
matrix *layoutMatrix
network SquareTreeNodeInterface
matrix *layoutMatrix
subnetMode bool
}

func newLayout(network SquareTreeNodeInterface) *layoutS {
return &layoutS{network: network, matrix: newLayoutMatrix()}
func newLayout(network SquareTreeNodeInterface, subnetMode bool) *layoutS {
return &layoutS{network: network, matrix: newLayoutMatrix(), subnetMode: subnetMode}
}

func (ly *layoutS) layout() {
// main layout algorithm:
// 1. create a 2D matrix - for each subnet icon, it set the location in the matrix
ly.layoutSubnetsIcons()
// in case of subnet mode, set the locations of the subnets
if !ly.subnetMode {
ly.layoutSubnetsIcons()
} else {
ly.layoutSubnets()
}
ly.matrix.removeUnusedLayers()
// 2. set the locations of the SG in the matrix, according to the locations of the icons
ly.setSGLocations()
Expand All @@ -80,7 +86,9 @@ func (ly *layoutS) layout() {
// 6. set the geometry for each node in the drawio
ly.matrix.setLayersDistance()
ly.setGeometries()
newLayoutOverlap(ly.network).fixOverlapping()
if !ly.subnetMode {
newLayoutOverlap(ly.network).fixOverlapping()
}
}

// setDefaultLocation() set locations to squares
Expand Down Expand Up @@ -275,6 +283,9 @@ func (ly *layoutS) layoutSubnetsIcons() {
for _, group := range groups {
rowIndex, colIndex = ly.layoutGroupIcons(group, rowIndex, colIndex)
}
if rowIndex == subnet.Location().firstRow.index {
rowIndex++
}
}
colIndex++
}
Expand All @@ -288,6 +299,100 @@ func (ly *layoutS) layoutSubnetsIcons() {
}
}

func (ly *layoutS) layoutSubnets() {
sly := newSubnetsLayout(ly.network)
sly.layout()
ly.setSubnetsLocations(sly.subnetMatrix, sly.zonesCol)
}

func (ly *layoutS) setSubnetsLocations(subnetMatrix [][]TreeNodeInterface, zonesCol map[TreeNodeInterface]int) {
locatedSubnets := map[TreeNodeInterface]bool{}
for ri, row := range subnetMatrix {
for ci, s := range row {
if s != nil && s != fakeSubnet {
ly.setDefaultLocation(s.(SquareTreeNodeInterface), ri, ci)
locatedSubnets[s] = true
}
}
}
ly.setDefaultLocation(ly.network, 0, 0)
for _, cloud := range ly.network.(*NetworkTreeNode).clouds {
for _, vpc := range cloud.(*CloudTreeNode).vpcs {
for _, zone := range vpc.(*VpcTreeNode).zones {
if _, ok := zonesCol[zone]; !ok {
zonesCol[zone] = len(zonesCol)
}
rowIndex := 0
for _, subnet := range zone.(*ZoneTreeNode).subnets {
if !locatedSubnets[subnet] {
a := len(subnetMatrix)
for rowIndex < a && zonesCol[zone] < len(subnetMatrix[rowIndex]) && subnetMatrix[rowIndex][zonesCol[zone]] != nil {
rowIndex++
}
ly.setDefaultLocation(subnet, rowIndex, zonesCol[zone])
rowIndex++
}
}
}
}
}
}

func (ly *layoutS) resolveGroupedSubnetsOverride() {
zivnevo marked this conversation as resolved.
Show resolved Hide resolved
allSubnetsSquares := map[*GroupSubnetsSquareTreeNode]bool{}
for _, tn := range getAllNodes(ly.network) {
if !tn.NotShownInDrawio() && tn.IsSquare() && tn.(SquareTreeNodeInterface).IsGroupSubnetsSquare() {
allSubnetsSquares[tn.(*GroupSubnetsSquareTreeNode)] = true
}
}
for foundOverlap := true; foundOverlap; {
foundOverlap = false
for tn1 := range allSubnetsSquares {
for tn2 := range allSubnetsSquares {
l1 := tn1.Location()
l2 := tn2.Location()
if tn1 == tn2 {
continue
}
if l1.firstRow == l2.firstRow || l1.firstCol == l2.firstCol || l1.lastRow == l2.lastRow || l1.lastCol == l2.lastCol {
if l1.xOffset == l2.xOffset {
toShrink := tn1
if len(tn2.groupedSubnets) < len(tn1.groupedSubnets) {
toShrink = tn2
}
toShrink.Location().xOffset += groupInnerBorderWidth
toShrink.Location().yOffset += groupInnerBorderWidth
toShrink.Location().xEndOffset += groupInnerBorderWidth
toShrink.Location().yEndOffset += groupInnerBorderWidth
foundOverlap = true
}
}
zivnevo marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
}

func (ly *layoutS) setGroupedSubnetsOffset() {
for _, tn := range getAllNodes(ly.network) {
switch {
case tn.NotShownInDrawio():
case !tn.IsSquare():
case tn.(SquareTreeNodeInterface).IsSubnet():
tn.Location().xOffset = borderWidth
tn.Location().yOffset = borderWidth
tn.Location().xEndOffset = borderWidth
tn.Location().yEndOffset = borderWidth

case tn.(SquareTreeNodeInterface).IsGroupSubnetsSquare():
tn.Location().xOffset = -groupBorderWidth
tn.Location().yOffset = -groupBorderWidth
tn.Location().xEndOffset = -groupBorderWidth
tn.Location().yEndOffset = -groupBorderWidth
}
}
ly.resolveGroupedSubnetsOverride()
}

// //////////////////////////////////////////////////////////////////////////////////////////
// SG can have more than one squares. so setSGLocations() will add treeNodes of the kind PartialSGTreeNode
// PartialSGTreeNode can not have more than one row. and can have only cell that contains icons that belong to the SG
Expand Down Expand Up @@ -400,10 +505,16 @@ func (ly *layoutS) setSquaresLocations() {
}
}
}
for _, groupSubnetsSquare := range vpc.(*VpcTreeNode).groupSubnetsSquares {
resolveSquareLocation(groupSubnetsSquare, 0, false)
}
}
}
ly.resolvePublicNetworkLocations()
resolveSquareLocation(ly.network, 1, false)
if ly.subnetMode {
ly.setGroupedSubnetsOffset()
}
}

// ////////////////////////////////////////////////////////////////////////////////////////
Expand Down
Loading
Loading