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

Topology command: open svg graph in the user’s preferred application #107

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ kuadrantctl [command] [subcommand] [flags]
| ------------ | ---------------------------------------------------------- |
| `completion` | Generate autocompletion scripts for the specified shell |
| `generate` | Commands related to Kubernetes Gateway API and Kuadrant resource generation from OpenAPI 3.x specifications |
| `topology` | Command related to Kuadrant topology |
| `help` | Help about any command |
| `version` | Print the version number of `kuadrantctl` |
| `version` | Print the version number of `kuadrantctl` |

### Flags

Expand Down Expand Up @@ -81,6 +82,29 @@ Generate Gateway API resources from an OpenAPI 3.x specification
| ---------- | ------------------------------------------------ | --------------------------------- |
| `httproute`| Generate Gateway API HTTPRoute from OpenAPI 3.0.X| `--oas string` Path to OpenAPI spec file (in JSON or YAML format), URL, or '-' to read from standard input (required). `-o` Output format: 'yaml' or 'json'. (default "yaml") |

#### `topology`

Export and visualize kuadrant topology

### Usage

```shell
$ kuadrantctl topology -h
Export and visualize kuadrant topology

Usage:
kuadrantctl topology [flags]

Flags:
-d, --dot string Graphviz DOT output file
-h, --help help for topology
-n, --namespace string Topology's namespace (default "kuadrant-system")
-o, --output string SVG image output file

Global Flags:
-v, --verbose verbose output
```

##### `generate kuadrant`

Generate Kuadrant resources from an OpenAPI 3.x specification
Expand Down
63 changes: 43 additions & 20 deletions cmd/topology.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package cmd

import (
"bytes"
"fmt"
"errors"
"os"
"os/exec"
"strings"

"github.com/goccy/go-graphviz"
"github.com/spf13/cobra"
Expand All @@ -15,20 +17,22 @@ import (
)

var (
topologyNS string
topologyOutputFile string
topologyNS string
topologySVGOutputFile string
topologyDOTOutputFile string
)

func topologyCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "topology",
Short: "Read kuadrant topology",
Long: "Read kuadrant topology",
Short: "Export and visualize kuadrant topology",
Long: "Export and visualize kuadrant topology",
RunE: runTopology,
}

cmd.Flags().StringVarP(&topologyNS, "namespace", "n", "kuadrant-system", "Topology's namespace")
cmd.Flags().StringVarP(&topologyOutputFile, "output", "o", "(required)", "Output file")
cmd.Flags().StringVarP(&topologySVGOutputFile, "output", "o", "", "SVG image output file")
cmd.Flags().StringVarP(&topologyDOTOutputFile, "dot", "d", "", "Graphviz DOT output file")
err := cmd.MarkFlagRequired("output")
if err != nil {
panic(err)
Expand All @@ -37,6 +41,9 @@ func topologyCommand() *cobra.Command {
}

func runTopology(cmd *cobra.Command, args []string) error {
if !strings.HasSuffix(topologySVGOutputFile, ".svg") {
return errors.New("output file must have .svg extension")
}
ctx := cmd.Context()
configuration, err := config.GetConfig()
if err != nil {
Expand All @@ -56,18 +63,18 @@ func runTopology(cmd *cobra.Command, args []string) error {
return err
}

topologyOutputFileInDotFormat := fmt.Sprintf("%s.dot", topologyOutputFile)

fDot, err := os.Create(topologyOutputFileInDotFormat)
if err != nil {
return err
}
defer fDot.Close()

_, err = fDot.WriteString(topologyConfigMap.Data["topology"])
logf.Log.V(1).Info("write topology in DOT format to file", "file", topologyOutputFileInDotFormat, "error", err)
if err != nil {
return err
if topologyDOTOutputFile != "" {
fDot, err := os.Create(topologyDOTOutputFile)
if err != nil {
return err
}
defer fDot.Close()

_, err = fDot.WriteString(topologyConfigMap.Data["topology"])
logf.Log.V(1).Info("write topology in DOT format to file", "file", topologyDOTOutputFile, "error", err)
if err != nil {
return err
}
}

g, err := graphviz.New(ctx)
Expand Down Expand Up @@ -96,17 +103,33 @@ func runTopology(cmd *cobra.Command, args []string) error {
}

// write to file
fSvg, err := os.Create(topologyOutputFile)
fSvg, err := os.Create(topologySVGOutputFile)
if err != nil {
return err
}
defer fSvg.Close()

_, err = fSvg.Write(buf.Bytes())
logf.Log.V(1).Info("write topology in SVG format to file", "file", topologyOutputFile, "error", err)
logf.Log.V(1).Info("write topology in SVG format to file", "file", topologySVGOutputFile, "error", err)
if err != nil {
return err
}

externalCommand := "xdg-open"
if _, err := exec.LookPath("open"); err == nil {
externalCommand = "open"
}

openCmd := exec.Command(externalCommand, topologySVGOutputFile)
// pipe the commands output to the applications
// standard output
openCmd.Stdout = os.Stdout

// Run still runs the command and waits for completion
// but the output is instantly piped to Stdout
if err := openCmd.Run(); err != nil {
return err
}

return nil
}
Loading