Skip to content

Commit

Permalink
Add traceflow octant-plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
Yiwei committed Jul 2, 2020
1 parent db8f1cf commit 7327e8e
Show file tree
Hide file tree
Showing 6 changed files with 732 additions and 1 deletion.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ require (
github.com/elazarl/goproxy v0.0.0-20190911111923-ecfe977594f1 // indirect
github.com/evanphx/json-patch v4.5.0+incompatible // indirect
github.com/go-openapi/spec v0.19.3
github.com/goccy/go-graphviz v0.0.5
github.com/gogo/protobuf v1.3.1
github.com/golang/mock v1.2.0
github.com/golang/protobuf v1.3.2
Expand Down
17 changes: 16 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea h1:n2Ltr3SrfQlf/9nOna1DoGKxLx3qTSI8Ttl6Xrqp6mw=
github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/corona10/goimagehash v1.0.2 h1:pUfB0LnsJASMPGEZLj7tGY251vF+qLGqOgEP4rUs6kA=
github.com/corona10/goimagehash v1.0.2/go.mod h1:/l9umBhvcHQXVtQO1V6Gp1yD20STawkhRnnX0D1bvVI=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ=
Expand Down Expand Up @@ -124,6 +126,8 @@ github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5I
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
Expand All @@ -148,12 +152,16 @@ github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh
github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/goccy/go-graphviz v0.0.5 h1:qcjgvNiYbLyfLAq9LvyYBJ7sNMbQh9w4FoAzBDrYhYw=
github.com/goccy/go-graphviz v0.0.5/go.mod h1:wXVsXxmyMQU6TN3zGRttjNn3h+iCAS7xQFC6TlNvLhk=
github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903 h1:LbsanbbD6LieFkXbj9YNNBupiGHJgFeLpO0j0Fza1h8=
Expand Down Expand Up @@ -208,6 +216,7 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
github.com/j-keck/arping v1.0.0 h1:DN6Wy73IeadEEo5xVCgEp+ZGn2xmAypggxj8mtxXBD0=
github.com/j-keck/arping v1.0.0/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
Expand Down Expand Up @@ -269,6 +278,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5 h1:BvoENQQU+fZ9uukda/RzCAL/191HHwJA5b13R6diVlY=
github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
Expand All @@ -285,8 +296,9 @@ github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.m
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
Expand Down Expand Up @@ -381,12 +393,15 @@ golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo=
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495 h1:I6A9Ag9FpEKOjcKrRNjQkPHawoXIhKyTGfvvjFAiiAk=
golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20200119044424-58c23975cae1 h1:5h3ngYt7+vXCDZCup/HkCQgW5XwmSvR/nA2JmJ0RErg=
golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
Expand Down
279 changes: 279 additions & 0 deletions pkg/graphviz/traceflow.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
// Copyright 2020 Antrea Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package graphviz

import (
"bytes"
"fmt"
"log"
"strings"

"github.com/goccy/go-graphviz"
"github.com/goccy/go-graphviz/cgraph"

opsv1alpha1 "github.com/vmware-tanzu/antrea/pkg/apis/ops/v1alpha1"
)

var (
clusterSrcName = "cluster_source"
clusterDstName = "cluster_dest"
)

func genSubGraph(graph *cgraph.Graph, result *opsv1alpha1.NodeResult, firstNodeName string, dir cgraph.DirType, addNodeNum int) []*cgraph.Node {
var nodes []*cgraph.Node
obs := result.Observations

// Show the name of cluster.
if len(result.Node) > 0 {
graph.SetLabel(result.Node)
if dir == cgraph.ForwardDir {
graph.SetLabelJust(cgraph.LeftJust)
} else {
graph.SetLabelJust(cgraph.RightJust)
}
}

// Construct the first node. Show it only if we know the name of it.
node, _ := graph.CreateNode(firstNodeName)
nodes = append(nodes, node)
if len(firstNodeName) > 0 {
node.SetFontColor("white")
node.SetColor("royalblue1")
node.SetStyle(cgraph.FilledNodeStyle)
} else {
node.SetStyle("invis")
}

// Reorder the observations according to the direction of edges.
if dir == cgraph.BackDir {
for i := len(obs)/2 - 1; i >= 0; i-- {
opp := len(obs) - 1 - i
obs[i], obs[opp] = obs[opp], obs[i]
}
}

// Draw the actual observations of traceflow.
for _, o := range obs {
// Construct node and edge.
nodeName := fmt.Sprintf("%s_%d", graph.Name(), len(nodes))
node, _ := graph.CreateNode(nodeName)
node.SetLabel(string(o.Component))
node.SetShape(cgraph.BoxShape)
node.SetStyle(cgraph.RoundedNodeStyle + "," + cgraph.FilledNodeStyle)
node.SetFontColor("white")
nodes = append(nodes, node)
if len(nodes) > 1 {
edgeName := fmt.Sprintf("%s_%d", graph.Name(), len(nodes))
edge, _ := graph.CreateEdge(edgeName, nodes[len(nodes)-2], nodes[len(nodes)-1])
edge.SetDir(dir)
edge.SetPenWidth(3.0)
edge.SetColor("limegreen")
if len(nodes) == 2 {
edge.SetMinLen(1 + addNodeNum)
} else {
edge.SetMinLen(1)
}
if o.Action == opsv1alpha1.Dropped && dir == cgraph.BackDir {
edge.SetStyle("invis")
}
}
// Set the pattern of node.
labelStr := string(o.Component)
if len(o.ComponentInfo) > 0 {
labelStr += "\n" + o.ComponentInfo
}
labelStr += "\n" + string(o.Action)
if o.Component == opsv1alpha1.NetworkPolicy && len(o.NetworkPolicy) > 0 {
labelStr += "\nNetpol: " + o.NetworkPolicy
}
if o.Action == opsv1alpha1.Dropped {
node.SetColor("violet")
} else {
node.SetColor("turquoise3")
if len(o.TunnelDstIP) > 0 {
labelStr += "\nTo: " + o.TunnelDstIP
}
}
node.SetLabel(labelStr)
}
return nodes
}

func isSender(result opsv1alpha1.NodeResult) bool {
if len(result.Observations) == 0 {
return false
}
if result.Observations[0].Component != opsv1alpha1.SpoofGuard || result.Observations[0].Action != opsv1alpha1.Forwarded {
return false
}
return true
}

func isReceiver(result opsv1alpha1.NodeResult) bool {
if len(result.Observations) == 0 {
return false
}
if result.Observations[0].Component != opsv1alpha1.Forwarding || result.Observations[0].Action != opsv1alpha1.Received {
return false
}
return true
}

func getNodeResult(tf *opsv1alpha1.Traceflow, fn func(result opsv1alpha1.NodeResult) bool) *opsv1alpha1.NodeResult {
for _, result := range tf.Status.Results {
if fn(result) {
return &result
}
}
return nil
}

func getSrcNodeName(tf *opsv1alpha1.Traceflow) string {
if len(tf.Spec.Source.Namespace) > 0 && len(tf.Spec.Source.Pod) > 0 {
return tf.Spec.Source.Namespace + "/" + tf.Spec.Source.Pod
}
return ""
}

func getDstNodeName(tf *opsv1alpha1.Traceflow) string {
if len(tf.Spec.Destination.Namespace) > 0 && len(tf.Spec.Destination.Pod) > 0 {
return tf.Spec.Destination.Namespace + "/" + tf.Spec.Destination.Pod
}
return ""
}

// In Graphviz, clusters are surrounded by a pair of "{}" with string "subgraph ClusterName" before them.
// The function finds the start and end index of specific cluster.
func findClusterString(graphStr string, clusterName string) (startIndex int, endIndex int) {
startIndex = strings.Index(graphStr, "subgraph "+clusterName)
if startIndex == -1 {
return 0, 1
}
endIndex = startIndex
for graphStr[endIndex] != '{' {
endIndex++
}
// Depth represents the number of "{" minus the number of "}" from the start index of current cluster to endIndex.
// When depth is zero for the first time, it indicates that we successfully find the end index of the cluster.
depth := 1
for depth > 0 {
endIndex++
if graphStr[endIndex] == '{' {
depth++
}
if graphStr[endIndex] == '}' {
depth--
}
}
return startIndex, endIndex + 1
}

func genOutput(g *graphviz.Graphviz, graph *cgraph.Graph, isSingleCluster bool) string {
var buf bytes.Buffer
if err := g.Render(graph, "dot", &buf); err != nil {
log.Fatal(err)
}
if err := graph.Close(); err != nil {
log.Fatal(err)
}
g.Close()

str := buf.String()
if isSingleCluster {
return str
}
// In Graphviz, cluster is a subgraph which is surrounded by a rectangle and the nodes belonging to the cluster are drawn together.
// Swap source and destination cluster if destination cluster appears before source cluster.
srcStartIdx, srcEndIdx := findClusterString(str, clusterSrcName)
dstStartIdx, dstEndIdx := findClusterString(str, clusterDstName)
if dstEndIdx <= srcStartIdx {
return str[:dstStartIdx] + str[srcStartIdx:srcEndIdx] + str[dstEndIdx:srcStartIdx] + str[dstStartIdx:dstEndIdx] + str[srcEndIdx:]
}
return str
}

func GenGraph(tf *opsv1alpha1.Traceflow) string {
var err error
g := graphviz.New()
graph, err := g.Graph()
if err != nil {
log.Fatal(err)
}
graph.SetCenter(true)
graph.SetLabel(tf.Name)
graph.SetLabelLocation(cgraph.TopLocation)

senderRst := getNodeResult(tf, isSender)
receiverRst := getNodeResult(tf, isReceiver)
if tf == nil || senderRst == nil || tf.Status.Phase != opsv1alpha1.Succeeded || len(senderRst.Observations) == 0 {
return genOutput(g, graph, true)
}

cluster1 := graph.SubGraph(clusterSrcName, 1)
cluster1.SetStyle(cgraph.FilledGraphStyle)
// Handle single node traceflow.
if receiverRst == nil {
nodes := genSubGraph(cluster1, senderRst, getSrcNodeName(tf), cgraph.ForwardDir, 0)
// Draw the destination pod and involved edge.
edgeName := fmt.Sprintf("%s_%d", cluster1.Name(), len(senderRst.Observations))
if len(nodes) == 0 {
return genOutput(g, graph, true)
}
switch senderRst.Observations[len(senderRst.Observations)-1].Action {
// If the last action of the sender is FORWARDED,
// then the packet has been sent out by sender, implying that there is a disconnection.
case opsv1alpha1.Forwarded:
lastNode, _ := graph.CreateNode(getDstNodeName(tf))
edge, _ := graph.CreateEdge(edgeName, nodes[len(nodes)-1], lastNode)
edge.SetColor("red")
edge.SetStyle(cgraph.DashedEdgeStyle)
case opsv1alpha1.Delivered:
lastNode, _ := cluster1.CreateNode(getDstNodeName(tf))
edge, _ := cluster1.CreateEdge(edgeName, nodes[len(nodes)-1], lastNode)
edge.SetPenWidth(3.0)
lastNode.SetFontColor("white")
lastNode.SetColor("royalblue1")
lastNode.SetStyle(cgraph.FilledNodeStyle)
edge.SetColor("limegreen")
}
return genOutput(g, graph, true)
}

// Make the graph centered by equalizing the number of nodes on both sides.
var nodeNum int
if len(senderRst.Observations) > len(receiverRst.Observations) {
nodeNum = len(senderRst.Observations)
} else {
nodeNum = len(receiverRst.Observations)
}

// Draw the nodes for the sender.
nodes1 := genSubGraph(cluster1, senderRst, getSrcNodeName(tf), cgraph.ForwardDir, nodeNum-len(senderRst.Observations))

// Draw the nodes for the receiver.
cluster2 := graph.SubGraph(clusterDstName, 1)
cluster2.SetStyle(cgraph.FilledGraphStyle)
nodes2 := genSubGraph(cluster2, receiverRst, getDstNodeName(tf), cgraph.BackDir, nodeNum-len(receiverRst.Observations))

// Draw the cross-cluster edge.
if len(nodes1) > 0 && len(nodes2) > 0 {
edge, _ := graph.CreateEdge("cross_node", nodes1[len(nodes1)-1], nodes2[len(nodes2)-1])
edge.SetConstraint(false)
edge.SetPenWidth(3.0)
edge.SetColor("limegreen")
}

return genOutput(g, graph, false)
}
5 changes: 5 additions & 0 deletions plugins/octant/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ antrea-octant-plugin:
@mkdir -p $(BINDIR)
GOOS=linux $(GO) build -o $(BINDIR) $(GOFLAGS) -ldflags '$(LDFLAGS)' github.com/vmware-tanzu/antrea/plugins/octant/cmd/antrea-octant-plugin

.PHONY: antrea-traceflow-plugin
antrea-traceflow-plugin:
@mkdir -p $(BINDIR)
GOOS=linux $(GO) build -o $(BINDIR) github.com/vmware-tanzu/antrea/plugins/octant/cmd/antrea-traceflow-plugin

.PHONY: octant-plugins
octant-plugins:
@mkdir -p $(BINDIR)
Expand Down
Loading

0 comments on commit 7327e8e

Please sign in to comment.