Skip to content

Commit

Permalink
Refactor command structure to make the command tree usable by other
Browse files Browse the repository at this point in the history
mains

This is the first step in refactor gnmic to allow for a minimum cli
which can be used as a lighterweight implementation for either on box
or in embedded or low dependency environments.
  • Loading branch information
marcushines committed Dec 7, 2023
1 parent d461fa9 commit 819b786
Show file tree
Hide file tree
Showing 18 changed files with 129 additions and 99 deletions.
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
package main

import (
"github.com/openconfig/gnmic/cmd"
"github.com/openconfig/gnmic/pkg/cmd"
)

func main() {
Expand Down
5 changes: 3 additions & 2 deletions cmd/capabilities.go → pkg/cmd/capabilities/capabilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
//
// SPDX-License-Identifier: Apache-2.0

package cmd
package capabilities

import (
"github.com/openconfig/gnmic/pkg/app"
"github.com/spf13/cobra"
)

// capabilitiesCmd represents the capabilities command
func newCapabilitiesCmd() *cobra.Command {
func New(gApp *app.App) *cobra.Command {
cmd := &cobra.Command{
Use: "capabilities",
Aliases: []string{"cap"},
Expand Down
5 changes: 3 additions & 2 deletions cmd/completion.go → pkg/cmd/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ package cmd
import (
"os"

"github.com/openconfig/gnmic/pkg/app"
"github.com/spf13/cobra"
)

// getCmd represents the get command
func newCompletionCmd() *cobra.Command {
// newCompletionCmd creates completion command tree.
func newCompletionCmd(gApp *app.App) *cobra.Command {
cmd := &cobra.Command{
Use: "completion [bash|zsh|fish]",
Short: "generate completion script",
Expand Down
13 changes: 7 additions & 6 deletions cmd/diff.go → pkg/cmd/diff/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
//
// SPDX-License-Identifier: Apache-2.0

package cmd
package diff

import (
"github.com/openconfig/gnmic/pkg/app"
"github.com/spf13/cobra"
)

// diffCmd represents the diff command
func newDiffCmd() *cobra.Command {
func New(gApp *app.App) *cobra.Command {
cmd := &cobra.Command{
Use: "diff",
Aliases: []string{"compare"},
Expand All @@ -23,13 +24,13 @@ func newDiffCmd() *cobra.Command {
SilenceUsage: true,
}
gApp.InitDiffFlags(cmd)
cmd.AddCommand(newDiffSetRequestCmd())
cmd.AddCommand(newDiffSetToNotifsCmd())
cmd.AddCommand(newDiffSetRequestCmd(gApp))
cmd.AddCommand(newDiffSetToNotifsCmd(gApp))
return cmd
}

// newDiffSetRequestCmd creates a new diff setrequest command.
func newDiffSetRequestCmd() *cobra.Command {
func newDiffSetRequestCmd(gApp *app.App) *cobra.Command {
cmd := &cobra.Command{
Use: "setrequest",
Short: "run a diff comparison between two setrequests in textproto format",
Expand All @@ -40,7 +41,7 @@ func newDiffSetRequestCmd() *cobra.Command {
return cmd
}

func newDiffSetToNotifsCmd() *cobra.Command {
func newDiffSetToNotifsCmd(gApp *app.App) *cobra.Command {
cmd := &cobra.Command{
Use: "set-to-notifs",
Short: "run a diff comparison between a SetRequest and a GetResponse or SubscribeResponse stream stored in textproto format",
Expand Down
14 changes: 9 additions & 5 deletions cmd/generate.go → pkg/cmd/generate/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,26 @@
//
// SPDX-License-Identifier: Apache-2.0

package cmd
package generate

import (
"github.com/openconfig/gnmic/pkg/app"
"github.com/spf13/cobra"
)

// generateCmd represents the generate command
func newGenerateCmd() *cobra.Command {
cmd := &cobra.Command{
func New(gApp *app.App) *cobra.Command {
genCmd := &cobra.Command{
Use: "generate",
Aliases: []string{"gen"},
Short: "generate paths or JSON/YAML objects from YANG",
PersistentPreRunE: gApp.GeneratePreRunE,
RunE: gApp.GenerateRunE,
SilenceUsage: true,
}
gApp.InitGenerateFlags(cmd)
return cmd
genCmd.AddCommand(newGenerateSetRequestCmd(gApp))
genCmd.AddCommand(newGeneratePathCmd(gApp))

gApp.InitGenerateFlags(genCmd)
return genCmd
}
5 changes: 3 additions & 2 deletions cmd/generatePath.go → pkg/cmd/generate/generatePath.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
//
// SPDX-License-Identifier: Apache-2.0

package cmd
package generate

import (
"github.com/openconfig/gnmic/pkg/app"
"github.com/spf13/cobra"
)

// newGeneratePathCmd represents the generate path command
func newGeneratePathCmd() *cobra.Command {
func newGeneratePathCmd(gApp *app.App) *cobra.Command {
cmd := &cobra.Command{
Use: "path",
Short: "generate xpath(s) from yang models",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
//
// SPDX-License-Identifier: Apache-2.0

package cmd
package generate

import (
"github.com/openconfig/gnmic/pkg/app"
"github.com/spf13/cobra"
)

// newGenerateSetRequestCmd represents the generate set-request command
func newGenerateSetRequestCmd() *cobra.Command {
func newGenerateSetRequestCmd(gApp *app.App) *cobra.Command {
cmd := &cobra.Command{
Use: "set-request",
Aliases: []string{"sr", "sreq", "srq"},
Expand Down
7 changes: 4 additions & 3 deletions cmd/get.go → pkg/cmd/get/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,22 @@
//
// SPDX-License-Identifier: Apache-2.0

package cmd
package get

import (
"github.com/openconfig/gnmic/pkg/app"
"github.com/spf13/cobra"
)

var dataType = [][2]string{
var DataType = [][2]string{
{"all", "all config/state/operational data"},
{"config", "data that the target considers to be read/write"},
{"state", "read-only data on the target"},
{"operational", "read-only data on the target that is related to software processes operating on the device, or external interactions of the device"},
}

// getCmd represents the get command
func newGetCmd() *cobra.Command {
func New(gApp *app.App) *cobra.Command {
cmd := &cobra.Command{
Use: "get",
Short: "run gnmi get on targets",
Expand Down
5 changes: 3 additions & 2 deletions cmd/getset.go → pkg/cmd/getset/getset.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
//
// SPDX-License-Identifier: Apache-2.0

package cmd
package getset

import (
"github.com/openconfig/gnmic/pkg/app"
"github.com/spf13/cobra"
)

// getCmd represents the get command
func newGetSetCmd() *cobra.Command {
func New(gApp *app.App) *cobra.Command {
cmd := &cobra.Command{
Use: "getset",
Aliases: []string{"gas", "gs"},
Expand Down
41 changes: 22 additions & 19 deletions cmd/listen.go → pkg/cmd/listener/listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
//
// SPDX-License-Identifier: Apache-2.0

package cmd
package listener

import (
"context"
Expand All @@ -22,6 +22,7 @@ import (
"github.com/jhump/protoreflect/dynamic"
nokiasros "github.com/karimra/sros-dialout"
"github.com/openconfig/gnmi/proto/gnmi"
"github.com/openconfig/gnmic/pkg/app"
"github.com/openconfig/gnmic/pkg/outputs"
"github.com/openconfig/gnmic/pkg/utils"
"github.com/prometheus/client_golang/prometheus/promhttp"
Expand All @@ -32,8 +33,8 @@ import (
"google.golang.org/grpc/peer"
)

// listenCmd represents the listen command
func newListenCmd() *cobra.Command {
// New returns the listen command tree.
func New(gApp *app.App) *cobra.Command {
cmd := &cobra.Command{
Use: "listen",
Short: "listens for telemetry dialout updates from the node",
Expand Down Expand Up @@ -145,7 +146,7 @@ func newListenCmd() *cobra.Command {
}()
defer httpServer.Close()
}

server.gApp = gApp
server.grpcServer.Serve(server.listener)
defer server.grpcServer.Stop()
return nil
Expand All @@ -167,25 +168,27 @@ type dialoutTelemetryServer struct {
Outputs map[string]outputs.Output

ctx context.Context

gApp *app.App
}

func (s *dialoutTelemetryServer) Publish(stream nokiasros.DialoutTelemetry_PublishServer) error {
peer, ok := peer.FromContext(stream.Context())
if ok && gApp.Config.Debug {
if ok && s.gApp.Config.Debug {
b, err := json.Marshal(peer)
if err != nil {
gApp.Logger.Printf("failed to marshal peer data: %v", err)
s.gApp.Logger.Printf("failed to marshal peer data: %v", err)
} else {
gApp.Logger.Printf("received Publish RPC from peer=%s", string(b))
s.gApp.Logger.Printf("received Publish RPC from peer=%s", string(b))
}
}
md, ok := metadata.FromIncomingContext(stream.Context())
if ok && gApp.Config.Debug {
if ok && s.gApp.Config.Debug {
b, err := json.Marshal(md)
if err != nil {
gApp.Logger.Printf("failed to marshal context metadata: %v", err)
s.gApp.Logger.Printf("failed to marshal context metadata: %v", err)
} else {
gApp.Logger.Printf("received http2_header=%s", string(b))
s.gApp.Logger.Printf("received http2_header=%s", string(b))
}
}
outMeta := outputs.Meta{}
Expand All @@ -194,27 +197,27 @@ func (s *dialoutTelemetryServer) Publish(stream nokiasros.DialoutTelemetry_Publi
outMeta["subscription-name"] = sn[0]
}
} else {
gApp.Logger.Println("could not find subscription-name in http2 headers")
s.gApp.Logger.Println("could not find subscription-name in http2 headers")
}
outMeta["source"] = peer.Addr.String()
if systemName, ok := md["system-name"]; ok {
if len(systemName) > 0 {
outMeta["system-name"] = systemName[0]
}
} else {
gApp.Logger.Println("could not find system-name in http2 headers")
s.gApp.Logger.Println("could not find system-name in http2 headers")
}
for {
subResp, err := stream.Recv()
if err != nil {
if err != io.EOF {
gApp.Logger.Printf("gRPC dialout receive error: %v", err)
s.gApp.Logger.Printf("gRPC dialout receive error: %v", err)
}
break
}
err = stream.Send(&nokiasros.PublishResponse{})
if err != nil {
gApp.Logger.Printf("error sending publish response to server: %v", err)
s.gApp.Logger.Printf("error sending publish response to server: %v", err)
}
switch resp := subResp.Response.(type) {
case *gnmi.SubscribeResponse_Update:
Expand All @@ -225,15 +228,15 @@ func (s *dialoutTelemetryServer) Publish(stream nokiasros.DialoutTelemetry_Publi
m := dynamic.NewMessage(s.rootDesc.GetFile().FindMessage("Nokia.SROS.root"))
err := m.Unmarshal(update.Val.GetProtoBytes())
if err != nil {
gApp.Logger.Printf("failed to unmarshal m: %v", err)
s.gApp.Logger.Printf("failed to unmarshal m: %v", err)
}
jsondata, err := m.MarshalJSON()
if err != nil {
gApp.Logger.Printf("failed to marshal dynamic proto msg: %v", err)
s.gApp.Logger.Printf("failed to marshal dynamic proto msg: %v", err)
continue
}
if gApp.Config.Debug {
gApp.Logger.Printf("json format=%s", string(jsondata))
if s.gApp.Config.Debug {
s.gApp.Logger.Printf("json format=%s", string(jsondata))
}
update.Val.Value = &gnmi.TypedValue_JsonVal{JsonVal: jsondata}
}
Expand All @@ -244,7 +247,7 @@ func (s *dialoutTelemetryServer) Publish(stream nokiasros.DialoutTelemetry_Publi
}

case *gnmi.SubscribeResponse_SyncResponse:
gApp.Logger.Printf("received sync response=%+v from %s", resp.SyncResponse, outMeta["source"])
s.gApp.Logger.Printf("received sync response=%+v from %s", resp.SyncResponse, outMeta["source"])
}
}
return nil
Expand Down
7 changes: 4 additions & 3 deletions cmd/path.go → pkg/cmd/path/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
//
// SPDX-License-Identifier: Apache-2.0

package cmd
package path

import (
"github.com/openconfig/gnmic/pkg/app"
"github.com/spf13/cobra"
)

// pathCmd represents the path command
func newPathCmd() *cobra.Command {
// New creates the path command tree.
func New(gApp *app.App) *cobra.Command {
cmd := &cobra.Command{
Use: "path",
Short: "generate gnmi or xpath style from yang file",
Expand Down
14 changes: 8 additions & 6 deletions cmd/prompt.go → pkg/cmd/prompt.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/pflag"

"github.com/openconfig/gnmic/pkg/cmd/get"
"github.com/openconfig/gnmic/pkg/cmd/subscribe"
"github.com/openconfig/gnmic/pkg/types"
)

Expand Down Expand Up @@ -630,20 +632,20 @@ func findDynamicSuggestions(annotation string, doc goprompt.Document) []goprompt
}
return goprompt.FilterHasPrefix(suggestions, doc.GetWordBeforeCursor(), true)
case "STORE":
suggestions := make([]goprompt.Suggest, 0, len(dataType))
for _, sugg := range dataType {
suggestions := make([]goprompt.Suggest, 0, len(get.DataType))
for _, sugg := range get.DataType {
suggestions = append(suggestions, goprompt.Suggest{Text: sugg[0], Description: sugg[1]})
}
return goprompt.FilterHasPrefix(suggestions, doc.GetWordBeforeCursor(), true)
case "SUBSC_MODE":
suggestions := make([]goprompt.Suggest, 0, len(subscriptionModes))
for _, sugg := range subscriptionModes {
suggestions := make([]goprompt.Suggest, 0, len(subscribe.Modes))
for _, sugg := range subscribe.Modes {
suggestions = append(suggestions, goprompt.Suggest{Text: sugg[0], Description: sugg[1]})
}
return goprompt.FilterHasPrefix(suggestions, doc.GetWordBeforeCursor(), true)
case "STREAM_MODE":
suggestions := make([]goprompt.Suggest, 0, len(streamSubscriptionModes))
for _, sugg := range streamSubscriptionModes {
suggestions := make([]goprompt.Suggest, 0, len(subscribe.StreamModes))
for _, sugg := range subscribe.StreamModes {
suggestions = append(suggestions, goprompt.Suggest{Text: sugg[0], Description: sugg[1]})
}
return goprompt.FilterHasPrefix(suggestions, doc.GetWordBeforeCursor(), true)
Expand Down
File renamed without changes.
Loading

0 comments on commit 819b786

Please sign in to comment.