Skip to content

Commit

Permalink
Add status command
Browse files Browse the repository at this point in the history
Signed-off-by: Ondrej Fabry <ofabry@cisco.com>
  • Loading branch information
ondrej-fabry committed Sep 2, 2019
1 parent 143842f commit 5660247
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 9 deletions.
4 changes: 2 additions & 2 deletions cmd/agentctl/commands/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func NewDumpCommand(cli *AgentCli) *cobra.Command {
cmd := &cobra.Command{
Use: "dump MODEL",
Aliases: []string{"d"},
Short: "Dump actual state view",
Short: "Dump running state",
Example: `
To dump VPP interfaces run:
$ agentctl dump vpp.interfaces
Expand Down Expand Up @@ -75,7 +75,7 @@ func runDump(cli *AgentCli, opts DumpOptions) {

var modelKeyPrefix string
for _, m := range cli.AllModels() {
if model == m.Alias || model == m.Name {
if (m.Alias != "" && model == m.Alias) || model == m.Name {
modelKeyPrefix = m.KeyPrefix
break
}
Expand Down
18 changes: 12 additions & 6 deletions cmd/agentctl/commands/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ import (
)

func NewGenerateCommand(cli *AgentCli) *cobra.Command {
var opts GenerateOptions

var (
opts GenerateOptions
)
cmd := &cobra.Command{
Use: "generate MODEL",
Aliases: []string{"gen"},
Expand All @@ -40,10 +41,11 @@ func NewGenerateCommand(cli *AgentCli) *cobra.Command {
},
DisableFlagsInUseLine: true,
}
cmd.PersistentFlags().StringVarP(&opts.Format, "format", "f", "json",
flags := cmd.Flags()
flags.StringVarP(&opts.Format, "format", "f", "json",
"Output formats: json, yaml")
cmd.PersistentFlags().BoolVar(&opts.OneLine, "oneline", false,
"Print output as single line. Works only with json format")
flags.BoolVar(&opts.OneLine, "oneline", false,
"Print output as single line (only json format)")
return cmd
}

Expand Down Expand Up @@ -73,6 +75,7 @@ func runGenerate(cli *AgentCli, opts GenerateOptions) {
var err error

switch strings.ToLower(opts.Format) {

case "j", "json":
m := jsonpb.Marshaler{
EnumsAsInts: false,
Expand All @@ -85,6 +88,7 @@ func runGenerate(cli *AgentCli, opts GenerateOptions) {
if err != nil {
ExitWithError(fmt.Errorf("Encoding to json failed: %v", err))
}

case "y", "yaml":
m := jsonpb.Marshaler{
EnumsAsInts: false,
Expand All @@ -95,19 +99,21 @@ func runGenerate(cli *AgentCli, opts GenerateOptions) {
}
out, err = m.MarshalToString(modelInstance)
if err != nil {
ExitWithError(fmt.Errorf("Encoding to json failed: %v", err))
ExitWithError(fmt.Errorf("encoding to json failed: %v", err))
}
b, err := yaml.JSONToYAML([]byte(out))
if err != nil {
ExitWithError(fmt.Errorf("Encoding to yaml failed: %v", err))
}
out = string(b)

case "p", "proto":
m := proto.TextMarshaler{
Compact: false,
ExpandAny: false,
}
out = m.Text(modelInstance)

default:
ExitWithError(fmt.Errorf("Unknown format: %s", opts.Format))
}
Expand Down
6 changes: 5 additions & 1 deletion cmd/agentctl/commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ func AddRootCommands(cmd *cobra.Command, cli *AgentCli) {
NewDumpCommand(cli),
NewKvdbCommand(cli),
NewGenerateCommand(cli),
NewStatusCommand(cli),
showCmd(),
)
}
Expand Down Expand Up @@ -128,7 +129,10 @@ Commands:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "help"))}}
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
Options:
{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}}
{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}
Global Flags:
{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}}
Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}}
{{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableSubCommands}}
Expand Down
138 changes: 138 additions & 0 deletions cmd/agentctl/commands/status.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// Copyright (c) 2019 Cisco and/or its affiliates.
//
// 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 commands

import (
"bytes"
"encoding/json"
"fmt"
"net/url"
"os"
"strings"
"text/tabwriter"

"github.com/spf13/cobra"

"github.com/ligato/vpp-agent/pkg/models"
"github.com/ligato/vpp-agent/plugins/kvscheduler/api"
)

func NewStatusCommand(cli *AgentCli) *cobra.Command {
var opts StatusOptions

cmd := &cobra.Command{
Use: "status",
Short: "Retrieve agent status",
Args: cobra.RangeArgs(0, 1),
Run: func(cmd *cobra.Command, args []string) {
opts.Models = args
runStatus(cli, opts)
},
DisableFlagsInUseLine: true,
}
return cmd
}

type StatusOptions struct {
Models []string
}

func runStatus(cli *AgentCli, opts StatusOptions) {
var model string
if len(opts.Models) > 0 {
model = opts.Models[0]
}

var modelKeyPrefix string
for _, m := range cli.AllModels() {
if (m.Alias != "" && model == m.Alias) || model == m.Name {
modelKeyPrefix = m.KeyPrefix
break
}
}

status, err := statusKeyPrefix(cli, modelKeyPrefix)
if err != nil {
ExitWithError(err)
}

printStatusTable(status)
}

// printStatusTable prints status data using table format
func printStatusTable(status []*api.BaseValueStatus) {
var buf bytes.Buffer
w := tabwriter.NewWriter(&buf, 10, 0, 3, ' ', 0)
fmt.Fprintf(w, "MODEL\tNAME\tSTATE\tDETAILS\tLAST OP\tERROR\t\n")

var printVal = func(val *api.ValueStatus) {
var (
model string
name string
)

m, err := models.GetModelForKey(val.Key)
if err != nil {
name = val.Key
} else {
model = fmt.Sprintf("%s.%s", m.Module, m.Type)
name = m.StripKeyPrefix(val.Key)
}

var lastOp string
if val.LastOperation != api.TxnOperation_UNDEFINED {
lastOp = val.LastOperation.String()
}
state := val.State.String()
if val.State == api.ValueState_OBTAINED {
state = strings.ToLower(state)
}

var details string
if len(val.Details) > 0 {
details = strings.Join(val.Details, ", ")
}

fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t\n", model, name, state, details, lastOp, val.Error)
}

for _, d := range status {
printVal(d.Value)
for _, v := range d.DerivedValues {
printVal(v)
}
}
if err := w.Flush(); err != nil {
return
}
fmt.Fprint(os.Stdout, buf.String())
}

func statusKeyPrefix(cli *AgentCli, keyPrefix string) ([]*api.BaseValueStatus, error) {
q := fmt.Sprintf(`/scheduler/status?key-prefix=%s`, url.QueryEscape(keyPrefix))
resp, err := cli.GET(q)
if err != nil {
return nil, err
}

Debugf("status resp: %s\n", resp)

var status []*api.BaseValueStatus
if err := json.Unmarshal(resp, &status); err != nil {
return nil, fmt.Errorf("decoding reply failed: %v", err)
}

return status, nil
}

0 comments on commit 5660247

Please sign in to comment.