Skip to content

Commit

Permalink
Add additional flags to swctl status command
Browse files Browse the repository at this point in the history
Signed-off-by: Peter Motičák <[email protected]>
  • Loading branch information
pemoticak committed Jul 10, 2023
1 parent d2bfbf4 commit 0b7432e
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 72 deletions.
12 changes: 4 additions & 8 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,15 @@ import (
"time"

docker "github.com/fsouza/go-dockerclient"
"github.com/sirupsen/logrus"
vppagent "go.ligato.io/vpp-agent/v3/cmd/agentctl/client"
"go.ligato.io/vpp-agent/v3/cmd/agentctl/client/tlsconfig"
linux_nsplugin "go.ligato.io/vpp-agent/v3/plugins/linux/nsplugin"

"go.pantheon.tech/stonework/plugins/cnfreg"
)

const (
DefaultHost = "127.0.0.1"
DefaultHTTPClientTimeout = 60 * time.Second
DefaultPortGRPC = 9991
DefaultPortHTTP = 9191
DockerComposeServiceLabel = "com.docker.compose.service"
)
Expand Down Expand Up @@ -75,7 +72,6 @@ type API interface {

// Client implements API interface.
type Client struct {
nsPlugin *linux_nsplugin.NsPlugin
dockerClient *docker.Client
httpClient *http.Client
host string
Expand All @@ -101,7 +97,9 @@ func NewClient(opts ...Option) (*Client, error) {
return nil, err
}
for _, o := range opts {
o(c)
if err = o(c); err != nil {
return nil, err
}
}

return c, nil
Expand Down Expand Up @@ -172,9 +170,7 @@ func (c *Client) GetComponents() ([]Component, error) {
return nil, err
}
containers = append(containers, c)
logrus.Warnf("[WLL] container name: %s, PID: %d, ENV: %+v", c.Name, c.State.Pid, c.Config.Env)
}
logrus.Warnf("[WLL] number of containers: &d", len(containers))

cnfInfos := make(map[string]cnfreg.Info)
for _, info := range infos {
Expand All @@ -201,7 +197,7 @@ func (c *Client) GetComponents() ([]Component, error) {
compo := &component{
agentclient: client,
Name: info.MsLabel,
Mode: cnfModeToCompoMode(info.Mode),
Mode: cnfModeToCompoMode(info.CnfMode),
Info: &info,
}
components = append(components, compo)
Expand Down
22 changes: 3 additions & 19 deletions client/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"fmt"

"go.ligato.io/cn-infra/v2/health/probe"
"go.ligato.io/vpp-agent/v3/cmd/agentctl/api/types"
"go.ligato.io/vpp-agent/v3/cmd/agentctl/client"

Expand All @@ -19,17 +18,16 @@ const (
// Foreign means the component is not managed by StoneWork
ComponentForeign ComponentMode = iota

// Stonework means the component is a StoneWork instance
ComponentStonework

// StoneworkModule means the component is a StoneWork module managed by StoneWork
ComponentStoneworkModule

// Stonework means the component is a StoneWork instance
ComponentStonework
)

// Component is a component of StoneWork. It can be StoneWork instance itself,
// a CNF connected to it or other Ligato service in connected to StoneWork.
type Component interface {
// Client() *client.Client
GetName() string
GetMode() ComponentMode
GetInfo() *cnfreg.Info
Expand Down Expand Up @@ -79,20 +77,6 @@ func (c *component) SchedulerValues() ([]*kvscheduler.BaseValueStatus, error) {
return values, nil
}

func (c *component) Readiness() (*probe.ExposedStatus, error) {
if c.Mode == ComponentForeign {
return nil, fmt.Errorf("cannot get readiness of component %s, this component in not managed by StoneWork", c.Name)
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

status, err := c.agentclient.Status(ctx)
if err != nil {
return nil, err
}
return status, nil
}

func cnfModeToCompoMode(cm cnfregpb.CnfMode) ComponentMode {
switch cm {
case cnfregpb.CnfMode_STANDALONE:
Expand Down
2 changes: 0 additions & 2 deletions cmd/swctl/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import (
"github.com/moby/term"
"github.com/sirupsen/logrus"

// agentcli "go.ligato.io/vpp-agent/v3/cmd/agentctl/cli"

"go.pantheon.tech/stonework/client"
)

Expand Down
84 changes: 46 additions & 38 deletions cmd/swctl/cmd_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ package main
import (
"fmt"
"io"
"os/exec"
"strconv"
"strings"
"sync"

"github.com/gookit/color"
"github.com/olekukonko/tablewriter"
"github.com/spf13/cobra"
"golang.org/x/exp/constraints"
"github.com/spf13/pflag"
"golang.org/x/exp/slices"

"go.ligato.io/vpp-agent/v3/proto/ligato/kvscheduler"
Expand All @@ -27,15 +28,23 @@ import (
const statusExample = `
<white># Show status for all components</>
$ <yellow>swctl status</>
<white># Show interface status of StoneWork VPP instance</>
$ <yellow>swctl status --show-interfaces</>
`

type StatusCmdOptions struct {
Args []string
Format string
type StatusOptions struct {
Format string
ShowInterfaces bool
}

func (opts *StatusOptions) InstallFlags(flagset *pflag.FlagSet) {
flagset.StringVar(&opts.Format, "format", "", "Format for the output (yaml, json, go template)")
flagset.BoolVar(&opts.ShowInterfaces, "show-interfaces", false, "Show interface status of StoneWork VPP instance")
}

func NewStatusCmd(cli Cli) *cobra.Command {
var opts StatusCmdOptions
var opts StatusOptions
cmd := &cobra.Command{
Use: "status [flags]",
Short: "Show status of StoneWork components",
Expand All @@ -45,10 +54,10 @@ func NewStatusCmd(cli Cli) *cobra.Command {
UnknownFlags: true,
},
RunE: func(cmd *cobra.Command, args []string) error {
opts.Args = args
return runStatusCmd(cli, opts)
},
}
opts.InstallFlags(cmd.PersistentFlags())
return cmd
}

Expand All @@ -57,7 +66,20 @@ type statusInfo struct {
ConfigCounts configCounts
}

func runStatusCmd(cli Cli, opts StatusCmdOptions) error {
func runStatusCmd(cli Cli, opts StatusOptions) error {
if opts.ShowInterfaces {
cmd := fmt.Sprintf("vpp-probe --env=%s --query label=%s=stonework discover", defaultVppProbeEnv, client.DockerComposeServiceLabel)
formatArg := fmt.Sprintf("--format=%s", opts.Format)
out, err := cli.Exec(cmd, []string{formatArg})
if err != nil {
if ee, ok := err.(*exec.ExitError); ok {
return fmt.Errorf("%v: %s", ee.String(), ee.Stderr)
}
}
fmt.Fprintln(cli.Out(), out)
return nil
}

resp, err := cli.Client().GetComponents()
if err != nil {
return err
Expand All @@ -71,11 +93,6 @@ func runStatusCmd(cli Cli, opts StatusCmdOptions) error {
var wg sync.WaitGroup
infoCh := make(chan infoWithErr)

type fetched struct {
values []*kvscheduler.BaseValueStatus
err error
}

for _, compo := range resp {
wg.Add(1)
go func(compo client.Component) {
Expand Down Expand Up @@ -108,11 +125,14 @@ func runStatusCmd(cli Cli, opts StatusCmdOptions) error {
}
infos = append(infos, i.statusInfo)
}
slices.SortFunc(infos, cmpInfos)
// if err := formatAsTemplate(cli.Out(), "json", resp); err != nil {
// return err
// }
printStatusTable(cli.Out(), infos)
slices.SortFunc(infos, cmpStatus)
if opts.Format == "" {
printStatusTable(cli.Out(), infos)
} else {
if err := formatAsTemplate(cli.Out(), opts.Format, infos); err != nil {
return err
}
}
return nil
}

Expand Down Expand Up @@ -143,24 +163,12 @@ func countConfig(baseVals []*kvscheduler.BaseValueStatus) configCounts {
return res
}

type comparable interface {
constraints.Integer | ~string
}

func less[T comparable](a, b T) bool {
if a > b {
return true
func cmpStatus(a, b statusInfo) bool {
greater := a.GetMode() > b.GetMode()
if !greater && a.GetMode() == b.GetMode() {
greater = a.GetName() > b.GetName()
}
return false
}

func cmpInfos(a, b statusInfo) bool {
res := less(a.GetMode(), b.GetMode())
bLessA := less(b.GetMode(), a.GetMode())
if !(res || bLessA) {
res = less(a.GetName(), b.GetName())
}
return res
return greater
}

func printStatusTable(out io.Writer, infos []statusInfo) {
Expand Down Expand Up @@ -193,8 +201,8 @@ func printStatusTable(out io.Writer, infos []statusInfo) {
table.Rich(row, clrs)
continue
}
config := info.ConfigCounts.String()
configColor := info.ConfigCounts.Color()
config := info.ConfigCounts.string()
configColor := info.ConfigCounts.color()
compoInfo := info.GetInfo()
grpcState := compoInfo.GRPCConnState.String()
var statusClr int
Expand Down Expand Up @@ -238,7 +246,7 @@ type configCounts struct {
Unimplemented int
}

func (c configCounts) String() string {
func (c configCounts) string() string {
var fields []string
if c.Ok != 0 {
fields = append(fields, fmt.Sprintf("%d OK", c.Ok))
Expand All @@ -265,7 +273,7 @@ func (c configCounts) String() string {
return strings.Join(fields, ", ")
}

func (c configCounts) Color() int {
func (c configCounts) color() int {
if c.Err > 0 {
return tablewriter.FgHiRedColor
}
Expand Down
4 changes: 2 additions & 2 deletions docs/SWCTL.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,14 +228,14 @@ swctl config history
#### Status

To display the status of StoneWork components and their interfaces, run:
To display the status of StoneWork components, run:

```bash
swctl status
```

> **Note**
> The `status` command is a simple wrapper for `vpp-probe discover`.
> When used with `--show-interfaces` flag the `status` command calls `vpp-probe discover`.
#### Trace

Expand Down
6 changes: 3 additions & 3 deletions plugins/cnfreg/rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import (
type Info struct {
PID int
MsLabel string
Mode pb.CnfMode
CnfMode pb.CnfMode
IPAddr string
GRPCPort int
HTTPPort int
Expand All @@ -54,7 +54,7 @@ func (p *Plugin) statusHandler(formatter *render.Render) http.HandlerFunc {
swInfo := &Info{
PID: os.Getpid(),
MsLabel: p.ServiceLabel.GetAgentLabel(),
Mode: pb.CnfMode_STONEWORK,
CnfMode: pb.CnfMode_STONEWORK,
IPAddr: p.ipAddress.String(),
GRPCPort: p.GRPCPlugin.GetPort(),
HTTPPort: p.HTTPPlugin.GetPort(),
Expand All @@ -66,7 +66,7 @@ func (p *Plugin) statusHandler(formatter *render.Render) http.HandlerFunc {
swModInfo := &Info{
PID: swMod.pid,
MsLabel: swMod.cnfMsLabel,
Mode: pb.CnfMode_STONEWORK_MODULE,
CnfMode: pb.CnfMode_STONEWORK_MODULE,
IPAddr: swMod.ipAddress,
GRPCPort: swMod.grpcPort,
HTTPPort: swMod.httpPort,
Expand Down

0 comments on commit 0b7432e

Please sign in to comment.