diff --git a/api/target.go b/api/target.go index 080e639..bb03518 100644 --- a/api/target.go +++ b/api/target.go @@ -13,6 +13,7 @@ import ( gnoios "github.com/openconfig/gnoi/os" "github.com/openconfig/gnoi/system" "google.golang.org/grpc" + "google.golang.org/grpc/metadata" ) var DefaultTargetTimeout = 10 * time.Second @@ -85,6 +86,18 @@ func (t *Target) CreateGrpcClient(ctx context.Context, opts ...grpc.DialOption) func (t *Target) Conn() grpc.ClientConnInterface { return t.client } +func (t *Target) AppendMetadata(ctx context.Context) context.Context { + kv := make([]string, 0, 4) + if t.Config.Username != nil { + kv = append(kv, "username", *t.Config.Username) + } + if t.Config.Password != nil { + kv = append(kv, "password", *t.Config.Password) + } + + return metadata.AppendToOutgoingContext(ctx, kv...) +} + func (t *Target) CertClient() cert.CertificateManagementClient { return cert.NewCertificateManagementClient(t.client) } diff --git a/app/app.go b/app/app.go index 7620123..770e4f4 100644 --- a/app/app.go +++ b/app/app.go @@ -1,7 +1,6 @@ package app import ( - "context" "fmt" "os" "sync" @@ -20,8 +19,6 @@ import ( ) type App struct { - ctx context.Context - Cfn context.CancelFunc RootCmd *cobra.Command wg *sync.WaitGroup @@ -33,12 +30,14 @@ type App struct { pm *sync.Mutex } +type TargetResponse interface { + Target() string + Response() any +} + func New() *App { - ctx, cancel := context.WithCancel(context.Background()) logger := log.New() a := &App{ - ctx: ctx, - Cfn: cancel, RootCmd: new(cobra.Command), wg: new(sync.WaitGroup), Config: config.New(), @@ -103,7 +102,7 @@ func (a *App) createBaseDialOpts() []grpc.DialOption { return opts } -func (a *App) printMsg(targetName string, m proto.Message) { +func (a *App) printProtoMsg(targetName string, m proto.Message) { if !a.Config.PrintProto { return } diff --git a/app/certCanGenerateCSR.go b/app/certCanGenerateCSR.go index 70ee156..ccab0b8 100644 --- a/app/certCanGenerateCSR.go +++ b/app/certCanGenerateCSR.go @@ -9,14 +9,22 @@ import ( "github.com/karimra/gnoic/api" gcert "github.com/karimra/gnoic/api/cert" "github.com/olekukonko/tablewriter" + "github.com/openconfig/gnoi/cert" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" ) type certCGCSRResponse struct { TargetError - can bool + rsp *cert.CanGenerateCSRResponse +} + +func (r *certCGCSRResponse) Target() string { + return r.TargetName +} + +func (r *certCGCSRResponse) Response() any { + return r.rsp } func (a *App) InitCertCanGenerateCSRFlags(cmd *cobra.Command) { @@ -42,38 +50,13 @@ func (a *App) RunECertCanGenerateCSR(cmd *cobra.Command, args []string) error { a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &certCGCSRResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - } - return - } - defer t.Close() - can, err := a.CertCanGenerateCSR(ctx, t) - responseChan <- &certCGCSRResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - can: can, - } - }(t) + go a.certCanGenerateCSRRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) errs := make([]error, 0, numTargets) - result := make([]*certCGCSRResponse, 0, numTargets) + result := make([]TargetResponse, 0, numTargets) for rsp := range responseChan { if rsp.Err != nil { wErr := fmt.Errorf("%q Cert CanGenerateCSR failed: %v", rsp.TargetName, rsp.Err) @@ -82,45 +65,90 @@ func (a *App) RunECertCanGenerateCSR(cmd *cobra.Command, args []string) error { continue } result = append(result, rsp) + a.printProtoMsg(rsp.TargetName, rsp.rsp) } - fmt.Print(certCGCSRTable(result)) + a.printCMDOutput(result, a.certCGCSRTable) return a.handleErrs(errs) } -func (a *App) CertCanGenerateCSR(ctx context.Context, t *api.Target) (bool, error) { +func (a *App) certCanGenerateCSRRequest(ctx context.Context, t *api.Target, rspCh chan<- *certCGCSRResponse) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &certCGCSRResponse{ + TargetError: TargetError{ + TargetName: t.Config.Address, + Err: err, + }, + } + return + } + defer t.Close() + rspCh <- a.certCanGenerateCSR(ctx, t) +} + +func (a *App) certCanGenerateCSR(ctx context.Context, t *api.Target) *certCGCSRResponse { req, err := gcert.NewCertCanGenerateCSRRequest( gcert.CertificateType(a.Config.CertCanGenerateCSRCertificateType), gcert.KeyType(a.Config.CertCanGenerateCSRKeyType), gcert.KeySize(a.Config.CertCanGenerateCSRKeySize), ) if err != nil { - return false, err + return &certCGCSRResponse{ + TargetError: TargetError{ + TargetName: t.Config.Name, + Err: err, + }, + } } - a.printMsg(t.Config.Name, req) + a.printProtoMsg(t.Config.Name, req) certClient := t.CertClient() resp, err := certClient.CanGenerateCSR(ctx, req) if err != nil { - return false, err + return &certCGCSRResponse{ + TargetError: TargetError{ + TargetName: t.Config.Name, + Err: err, + }, + } } - a.printMsg(t.Config.Name, resp) + a.printProtoMsg(t.Config.Name, resp) a.Logger.Infof("%q key-type=%s, cert-type=%s, key-size=%d: can_generate: %v", t.Config.Address, a.Config.CertCanGenerateCSRKeyType, a.Config.CertCanGenerateCSRCertificateType, a.Config.CertCanGenerateCSRKeySize, resp.GetCanGenerate()) - return resp.GetCanGenerate(), nil + return &certCGCSRResponse{ + TargetError: TargetError{ + TargetName: t.Config.Name, + Err: err, + }, + rsp: resp, + } } -func certCGCSRTable(rsps []*certCGCSRResponse) string { +func (a *App) certCGCSRTable(rsps []TargetResponse) string { tabData := make([][]string, 0, len(rsps)) + sort.Slice(rsps, func(i, j int) bool { + return rsps[i].Target() < rsps[j].Target() + }) for _, rsp := range rsps { - tabData = append(tabData, []string{ - rsp.TargetName, - fmt.Sprintf("%t", rsp.can), - }) + switch r := rsp.Response().(type) { + case *cert.CanGenerateCSRResponse: + tabData = append(tabData, []string{ + rsp.Target(), + fmt.Sprintf("%t", r.GetCanGenerate()), + }) + default: + a.Logger.Printf("%s: unexpected message type: %T", rsp.Target(), rsp.Response()) + } } sort.Slice(tabData, func(i, j int) bool { return tabData[i][0] < tabData[j][0] diff --git a/app/certGenerateCSR.go b/app/certGenerateCSR.go index 3e736fa..3101de1 100644 --- a/app/certGenerateCSR.go +++ b/app/certGenerateCSR.go @@ -11,7 +11,6 @@ import ( "github.com/openconfig/gnoi/cert" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" ) type certGenCSRResponse struct { @@ -22,7 +21,6 @@ type certGenCSRResponse struct { func (a *App) InitCertGenerateCSRFlags(cmd *cobra.Command) { cmd.ResetFlags() // - // cmd.Flags().StringVar(&a.Config.CertGenerateCSRCertificateID, "id", "", "Certificate ID") cmd.Flags().StringVar(&a.Config.CertGenerateCSRKeyType, "key-type", "KT_RSA", "Key Type") cmd.Flags().StringVar(&a.Config.CertGenerateCSRCertificateType, "cert-type", "CT_X509", "Certificate Type") @@ -51,31 +49,7 @@ func (a *App) RunEGenerateCSR(cmd *cobra.Command, args []string) error { responseChan := make(chan *certGenCSRResponse, numTargets) a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &certGenCSRResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - } - return - } - defer t.Close() - rsp, err := a.CertGenerateCSR(ctx, t) - responseChan <- &certGenCSRResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - rsp: rsp, - } - }(t) + go a.certGenerateCSRRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) @@ -121,13 +95,13 @@ func (a *App) CertGenerateCSR(ctx context.Context, t *api.Target) (*cert.Generat if err != nil { return nil, err } - a.printMsg(t.Config.Name, req) + a.printProtoMsg(t.Config.Name, req) certClient := t.CertClient() resp, err := certClient.GenerateCSR(ctx, req) if err != nil { return nil, err } - a.printMsg(t.Config.Name, resp) + a.printProtoMsg(t.Config.Name, resp) return resp, nil } @@ -154,3 +128,30 @@ func (a *App) saveCSR(rsp *certGenCSRResponse) error { } return nil } + +func (a *App) certGenerateCSRRequest(ctx context.Context, t *api.Target, rspCh chan<- *certGenCSRResponse) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &certGenCSRResponse{ + TargetError: TargetError{ + TargetName: t.Config.Address, + Err: err, + }, + } + return + } + defer t.Close() + rsp, err := a.CertGenerateCSR(ctx, t) + rspCh <- &certGenCSRResponse{ + TargetError: TargetError{ + TargetName: t.Config.Address, + Err: err, + }, + rsp: rsp, + } +} diff --git a/app/certGetCertificates.go b/app/certGetCertificates.go index b09262b..72d7546 100644 --- a/app/certGetCertificates.go +++ b/app/certGetCertificates.go @@ -18,7 +18,6 @@ import ( "github.com/openconfig/gnoi/cert" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" ) type getCertificatesResponse struct { @@ -26,6 +25,14 @@ type getCertificatesResponse struct { rsp *cert.GetCertificatesResponse } +func (r *getCertificatesResponse) Target() string { + return r.TargetName +} + +func (r *getCertificatesResponse) Response() any { + return r.rsp +} + func (a *App) InitCertGetCertificatesFlags(cmd *cobra.Command) { cmd.ResetFlags() // @@ -49,33 +56,7 @@ func (a *App) RunECertGetCertificates(cmd *cobra.Command, args []string) error { a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &getCertificatesResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - } - return - } - defer t.Close() - a.Logger.Debugf("%q gRPC client created", t.Config.Address) - rsp, err := a.CertGetCertificates(ctx, t) - responseChan <- &getCertificatesResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - rsp: rsp, - } - }(t) + go a.certGetCertificatesRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) @@ -140,6 +121,27 @@ func (a *App) RunECertGetCertificates(cmd *cobra.Command, args []string) error { return a.handleErrs(errs) } +func (a *App) certGetCertificatesRequest(ctx context.Context, t *api.Target, rspCh chan<- *getCertificatesResponse) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &getCertificatesResponse{ + TargetError: TargetError{ + TargetName: t.Config.Address, + Err: err, + }, + } + return + } + defer t.Close() + a.Logger.Debugf("%q gRPC client created", t.Config.Address) + rspCh <- a.CertGetCertificates(ctx, t) +} + func (a *App) certTable(rsps []*getCertificatesResponse) (string, error) { tabData := make([][]string, 0) for _, rsp := range rsps { @@ -182,14 +184,25 @@ func (a *App) certTable(rsps []*getCertificatesResponse) (string, error) { return b.String(), nil } -func (a *App) CertGetCertificates(ctx context.Context, t *api.Target) (*cert.GetCertificatesResponse, error) { +func (a *App) CertGetCertificates(ctx context.Context, t *api.Target) *getCertificatesResponse { resp, err := t.CertClient().GetCertificates(ctx, new(cert.GetCertificatesRequest)) if err != nil { - return nil, err + return &getCertificatesResponse{ + TargetError: TargetError{ + TargetName: t.Config.Name, + Err: err, + }, + } } - a.printMsg(t.Config.Name, resp) - return resp, nil + a.printProtoMsg(t.Config.Name, resp) + return &getCertificatesResponse{ + TargetError: TargetError{ + TargetName: t.Config.Name, + Err: err, + }, + rsp: resp, + } } func (a *App) saveCerts(rsp *getCertificatesResponse) { diff --git a/app/certInstall.go b/app/certInstall.go index fdb8ea7..5fee6b1 100644 --- a/app/certInstall.go +++ b/app/certInstall.go @@ -19,7 +19,6 @@ import ( "github.com/openconfig/gnoi/cert" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" "google.golang.org/protobuf/encoding/prototext" ) @@ -72,28 +71,9 @@ func (a *App) RunECertInstall(cmd *cobra.Command, args []string) error { responseChan := make(chan *TargetError, numTargets) a.wg.Add(numTargets) - for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &TargetError{ - TargetName: t.Config.Address, - Err: err, - } - return - } - defer t.Close() - err = a.CertInstall(ctx, t) - responseChan <- &TargetError{ - TargetName: t.Config.Address, - Err: err, - } - }(t) + for _, t := range targets { + go a.certCertificateInstallRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) @@ -104,13 +84,34 @@ func (a *App) RunECertInstall(cmd *cobra.Command, args []string) error { wErr := fmt.Errorf("%q Cert Install failed: %v", rsp.TargetName, rsp.Err) a.Logger.Error(wErr) errs = append(errs, wErr) - continue } } return a.handleErrs(errs) } -func (a *App) CertInstall(ctx context.Context, t *api.Target) error { +func (a *App) certCertificateInstallRequest(ctx context.Context, t *api.Target, rspCh chan<- *TargetError) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &TargetError{ + TargetName: t.Config.Address, + Err: err, + } + return + } + defer t.Close() + err = a.certInstall(ctx, t) + rspCh <- &TargetError{ + TargetName: t.Config.Address, + Err: err, + } +} + +func (a *App) certInstall(ctx context.Context, t *api.Target) error { // create cert mgmt install stream RPC stream, err := t.CertClient().Install(ctx) if err != nil { @@ -321,7 +322,7 @@ func (a *App) createRemoteCSRInstall(stream cert.CertificateManagement_InstallCl if err != nil { return nil, err } - a.printMsg(t.Config.Name, req) + a.printProtoMsg(t.Config.Name, req) err = stream.Send(req) if err != nil { @@ -335,7 +336,7 @@ func (a *App) createRemoteCSRInstall(stream cert.CertificateManagement_InstallCl return nil, fmt.Errorf("%q returned a CSR response", t.Config.Address) } if !a.Config.CertInstallPrintCSR { - a.printMsg(t.Config.Name, resp) + a.printProtoMsg(t.Config.Name, resp) } if a.Config.CertInstallPrintCSR { fmt.Printf("%q genCSR response:\n %s\n", t.Config.Address, prototext.Format(resp)) diff --git a/app/certLoadCerts.go b/app/certLoadCerts.go index 68a3f07..90a4597 100644 --- a/app/certLoadCerts.go +++ b/app/certLoadCerts.go @@ -8,17 +8,11 @@ import ( "github.com/openconfig/gnoi/cert" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" "github.com/karimra/gnoic/api" gcert "github.com/karimra/gnoic/api/cert" ) -type certLoadCert struct { - TargetError - rsp *cert.LoadCertificateResponse -} - func (a *App) InitCertLoadCertsFlags(cmd *cobra.Command) { cmd.ResetFlags() @@ -41,40 +35,15 @@ func (a *App) RunELoadCerts(cmd *cobra.Command, args []string) error { } numTargets := len(targets) - responseChan := make(chan *certLoadCert, numTargets) + responseChan := make(chan *TargetError, numTargets) a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &certLoadCert{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - } - return - } - defer t.Close() - rsp, err := a.CertLoadCertificate(ctx, t) - responseChan <- &certLoadCert{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - rsp: rsp, - } - }(t) + go a.certLoadCertificateRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) errs := make([]error, 0, numTargets) - // result := make([]*certLoadCert, 0, numTargets) for rsp := range responseChan { if rsp.Err != nil { @@ -83,18 +52,38 @@ func (a *App) RunELoadCerts(cmd *cobra.Command, args []string) error { errs = append(errs, wErr) continue } - // result = append(result, rsp) } return a.handleErrs(errs) } +func (a *App) certLoadCertificateRequest(ctx context.Context, t *api.Target, rspCh chan<- *TargetError) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &TargetError{ + TargetName: t.Config.Address, + Err: err, + } + return + } + defer t.Close() + _, err = a.CertLoadCertificate(ctx, t) + rspCh <- &TargetError{ + TargetName: t.Config.Address, + Err: err, + } +} + func (a *App) CertLoadCertificate(ctx context.Context, t *api.Target) (*cert.LoadCertificateResponse, error) { var err error opts := []gcert.CertOption{ gcert.CertificateType(a.Config.CertLoadCertificateCertificateID), } - // certClient := t.CertClient() if a.Config.CertLoadCertificateCertificate != "" { b, err := os.ReadFile(a.Config.CertLoadCertificateCertificate) @@ -145,13 +134,13 @@ func (a *App) CertLoadCertificate(ctx context.Context, t *api.Target) (*cert.Loa if err != nil { return nil, err } - a.printMsg(t.Config.Name, req) + a.printProtoMsg(t.Config.Name, req) resp, err := t.CertClient().LoadCertificate(ctx, req) if err != nil { return nil, err } - a.printMsg(t.Config.Name, resp) + a.printProtoMsg(t.Config.Name, resp) return resp, nil } diff --git a/app/certLoadCertsCaBundle.go b/app/certLoadCertsCaBundle.go index 031b4f9..f41626d 100644 --- a/app/certLoadCertsCaBundle.go +++ b/app/certLoadCertsCaBundle.go @@ -8,17 +8,11 @@ import ( "github.com/openconfig/gnoi/cert" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" "github.com/karimra/gnoic/api" gcert "github.com/karimra/gnoic/api/cert" ) -type certLoadCABundle struct { - TargetError - rsp *cert.LoadCertificateAuthorityBundleResponse -} - func (a *App) InitCertLoadCertsCaBundleFlags(cmd *cobra.Command) { cmd.ResetFlags() @@ -36,34 +30,10 @@ func (a *App) RunELoadCertsCaBundle(cmd *cobra.Command, args []string) error { } numTargets := len(targets) - responseChan := make(chan *certLoadCABundle, numTargets) + responseChan := make(chan *TargetError, numTargets) a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &certLoadCABundle{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - } - return - } - defer t.Close() - rsp, err := a.CertLoadCABundle(ctx, t) - responseChan <- &certLoadCABundle{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - rsp: rsp, - } - }(t) + go a.certLoadCertsCABundleRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) @@ -83,7 +53,29 @@ func (a *App) RunELoadCertsCaBundle(cmd *cobra.Command, args []string) error { return a.handleErrs(errs) } -func (a *App) CertLoadCABundle(ctx context.Context, t *api.Target) (*cert.LoadCertificateAuthorityBundleResponse, error) { +func (a *App) certLoadCertsCABundleRequest(ctx context.Context, t *api.Target, rspCh chan<- *TargetError) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &TargetError{ + TargetName: t.Config.Address, + Err: err, + } + return + } + defer t.Close() + _, err = a.certLoadCABundle(ctx, t) + rspCh <- &TargetError{ + TargetName: t.Config.Address, + Err: err, + } +} + +func (a *App) certLoadCABundle(ctx context.Context, t *api.Target) (*cert.LoadCertificateAuthorityBundleResponse, error) { var err error n := len(a.Config.CertLoadCertificateCaBundleCaCertificates) @@ -106,11 +98,11 @@ func (a *App) CertLoadCABundle(ctx context.Context, t *api.Target) (*cert.LoadCe if err != nil { return nil, err } - a.printMsg(t.Config.Name, req) + a.printProtoMsg(t.Config.Name, req) resp, err := t.CertClient().LoadCertificateAuthorityBundle(ctx, req) if err != nil { return nil, err } - a.printMsg(t.Config.Name, resp) + a.printProtoMsg(t.Config.Name, resp) return resp, nil } diff --git a/app/certRevoke.go b/app/certRevoke.go index 3f5862f..4d5cb2d 100644 --- a/app/certRevoke.go +++ b/app/certRevoke.go @@ -10,7 +10,6 @@ import ( "github.com/openconfig/gnoi/cert" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" ) func (a *App) InitCertRevokeCertificatesFlags(cmd *cobra.Command) { @@ -38,26 +37,7 @@ func (a *App) RunECertRevokeCertificates(cmd *cobra.Command, args []string) erro a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &TargetError{ - TargetName: t.Config.Address, - Err: err, - } - return - } - defer t.Close() - err = a.Revoke(ctx, t) - responseChan <- &TargetError{ - TargetName: t.Config.Address, - Err: err, - } - }(t) + go a.certRevokeRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) @@ -74,7 +54,29 @@ func (a *App) RunECertRevokeCertificates(cmd *cobra.Command, args []string) erro return a.handleErrs(errs) } -func (a *App) Revoke(ctx context.Context, t *api.Target) error { +func (a *App) certRevokeRequest(ctx context.Context, t *api.Target, rspCh chan<- *TargetError) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &TargetError{ + TargetName: t.Config.Name, + Err: err, + } + return + } + defer t.Close() + err = a.certRevoke(ctx, t) + rspCh <- &TargetError{ + TargetName: t.Config.Name, + Err: err, + } +} + +func (a *App) certRevoke(ctx context.Context, t *api.Target) error { certClient := t.CertClient() // opts := make([]gcert.CertOption, 0, len(a.Config.CertRevokeCertificatesCertificateID)) @@ -98,12 +100,12 @@ func (a *App) Revoke(ctx context.Context, t *api.Target) error { return err } - a.printMsg(t.Config.Name, req) + a.printProtoMsg(t.Config.Name, req) resp, err := certClient.RevokeCertificates(ctx, req) if err != nil { return err } - a.printMsg(t.Config.Name, resp) + a.printProtoMsg(t.Config.Name, resp) for _, revokeErr := range resp.CertificateRevocationError { a.Logger.Errorf("%q certificateID=%s revoke failed: %v\n", t.Config.Address, revokeErr.GetCertificateId(), revokeErr.GetErrorMessage()) } diff --git a/app/certRotate.go b/app/certRotate.go index 937dec1..dd0cf23 100644 --- a/app/certRotate.go +++ b/app/certRotate.go @@ -20,7 +20,6 @@ import ( "github.com/openconfig/gnoi/cert" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" "google.golang.org/protobuf/encoding/prototext" ) @@ -74,26 +73,7 @@ func (a *App) RunECertRotate(cmd *cobra.Command, args []string) error { a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &TargetError{ - TargetName: t.Config.Address, - Err: err, - } - return - } - defer t.Close() - err = a.CertRotate(ctx, t) - responseChan <- &TargetError{ - TargetName: t.Config.Address, - Err: err, - } - }(t) + go a.certRotateRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) @@ -110,7 +90,29 @@ func (a *App) RunECertRotate(cmd *cobra.Command, args []string) error { return a.handleErrs(errs) } -func (a *App) CertRotate(ctx context.Context, t *api.Target) error { +func (a *App) certRotateRequest(ctx context.Context, t *api.Target, rspCh chan<- *TargetError) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &TargetError{ + TargetName: t.Config.Address, + Err: err, + } + return + } + defer t.Close() + err = a.certRotate(ctx, t) + rspCh <- &TargetError{ + TargetName: t.Config.Address, + Err: err, + } +} + +func (a *App) certRotate(ctx context.Context, t *api.Target) error { certClient := t.CertClient() stream, err := certClient.Rotate(ctx) if err != nil { @@ -190,7 +192,7 @@ func (a *App) CertRotate(ctx context.Context, t *api.Target) error { if err != nil { return err } - a.printMsg(t.Config.Name, loadCertReq) + a.printProtoMsg(t.Config.Name, loadCertReq) err = stream.Send(loadCertReq) if err != nil { return fmt.Errorf("%q failed sending RotateRequest: %v", t.Config.Address, err) @@ -199,9 +201,9 @@ func (a *App) CertRotate(ctx context.Context, t *api.Target) error { if err != nil { return err } - a.printMsg(t.Config.Name, resp) + a.printProtoMsg(t.Config.Name, resp) - a.printMsg(t.Config.Name, gcert.NewCertRotateFinalizeRequest()) + a.printProtoMsg(t.Config.Name, gcert.NewCertRotateFinalizeRequest()) err = stream.Send(gcert.NewCertRotateFinalizeRequest()) if err != nil { return fmt.Errorf("%q RotateRequest FinalizeRequest RPC failed: %v", t.Config.Address, err) @@ -210,7 +212,7 @@ func (a *App) CertRotate(ctx context.Context, t *api.Target) error { if err != nil && !errors.Is(err, io.EOF) { return err } - a.printMsg(t.Config.Name, resp) + a.printProtoMsg(t.Config.Name, resp) a.Logger.Infof("%q Rotate RPC successful", t.Config.Address) return nil } @@ -319,7 +321,7 @@ func (a *App) createRemoteCSRRotate(stream cert.CertificateManagement_RotateClie if err != nil { return nil, err } - a.printMsg(t.Config.Name, req) + a.printProtoMsg(t.Config.Name, req) err = stream.Send(req) if err != nil { return nil, fmt.Errorf("%q failed send Rotate RPC: GenCSR: %v", err, t.Config.Address) @@ -331,7 +333,7 @@ func (a *App) createRemoteCSRRotate(stream cert.CertificateManagement_RotateClie if resp == nil { return nil, fmt.Errorf("%q returned a CSR response", t.Config.Address) } - a.printMsg(t.Config.Name, resp) + a.printProtoMsg(t.Config.Name, resp) if a.Config.CertRotatePrintCSR { fmt.Printf("%q genCSR response:\n %s\n", t.Config.Address, prototext.Format(resp)) } diff --git a/app/factory_reset.go b/app/factory_reset.go index 29bf681..4f27e58 100644 --- a/app/factory_reset.go +++ b/app/factory_reset.go @@ -8,7 +8,6 @@ import ( "github.com/openconfig/gnoi/factory_reset" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" ) type factoryResetStartResponse struct { @@ -38,25 +37,7 @@ func (a *App) RunEFactoryResetStart(cmd *cobra.Command, args []string) error { a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &factoryResetStartResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - } - return - } - defer t.Close() - responseChan <- a.FactoryResetStart(ctx, t) - }(t) + go a.factoryResetStartRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) @@ -73,17 +54,37 @@ func (a *App) RunEFactoryResetStart(cmd *cobra.Command, args []string) error { result = append(result, rsp) } for _, r := range result { - a.printMsg(r.TargetName, r.rsp) + a.printProtoMsg(r.TargetName, r.rsp) } return a.handleErrs(errs) } -func (a *App) FactoryResetStart(ctx context.Context, t *api.Target) *factoryResetStartResponse { +func (a *App) factoryResetStartRequest(ctx context.Context, t *api.Target, rspCh chan<- *factoryResetStartResponse) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &factoryResetStartResponse{ + TargetError: TargetError{ + TargetName: t.Config.Address, + Err: err, + }, + } + return + } + defer t.Close() + rspCh <- a.factoryResetStart(ctx, t) +} + +func (a *App) factoryResetStart(ctx context.Context, t *api.Target) *factoryResetStartResponse { req := &factory_reset.StartRequest{ FactoryOs: a.Config.FactoryResetStartFactoryOS, ZeroFill: a.Config.FactoryResetStartZeroFill, } - a.printMsg(t.Config.Name, req) + a.printProtoMsg(t.Config.Name, req) fr := factory_reset.NewFactoryResetClient(t.Conn()) rsp, err := fr.Start(ctx, req) return &factoryResetStartResponse{ diff --git a/app/file.go b/app/file.go index 7741acc..9798443 100644 --- a/app/file.go +++ b/app/file.go @@ -2,21 +2,10 @@ package app import ( "context" - "fmt" "github.com/openconfig/gnoi/file" - "github.com/spf13/cobra" - "github.com/spf13/pflag" ) -func (a *App) InitFileFlags(cmd *cobra.Command) { - cmd.ResetFlags() - // - cmd.LocalFlags().VisitAll(func(flag *pflag.Flag) { - a.Config.FileConfig.BindPFlag(fmt.Sprintf("%s-%s", cmd.Name(), flag.Name), flag) - }) -} - func (a *App) isDir(ctx context.Context, fileClient file.FileClient, path string) (bool, error) { r, err := fileClient.Stat(ctx, &file.StatRequest{ Path: path, diff --git a/app/fileGet.go b/app/fileGet.go index c53c0f3..e137ab6 100644 --- a/app/fileGet.go +++ b/app/fileGet.go @@ -17,7 +17,6 @@ import ( "github.com/openconfig/gnoi/types" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" "google.golang.org/protobuf/encoding/prototext" ) @@ -49,32 +48,7 @@ func (a *App) RunEFileGet(cmd *cobra.Command, args []string) error { a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &fileGetResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - } - return - } - defer t.Close() - filename, err := a.FileGet(ctx, t) - responseChan <- &fileGetResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - file: filename, - } - }(t) + go a.fileGetRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) @@ -99,13 +73,40 @@ func (a *App) RunEFileGet(cmd *cobra.Command, args []string) error { return a.handleErrs(errs) } -func (a *App) FileGet(ctx context.Context, t *api.Target) ([]string, error) { +func (a *App) fileGetRequest(ctx context.Context, t *api.Target, rspCh chan<- *fileGetResponse) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &fileGetResponse{ + TargetError: TargetError{ + TargetName: t.Config.Address, + Err: err, + }, + } + return + } + defer t.Close() + filename, err := a.fileGet(ctx, t) + rspCh <- &fileGetResponse{ + TargetError: TargetError{ + TargetName: t.Config.Address, + Err: err, + }, + file: filename, + } +} + +func (a *App) fileGet(ctx context.Context, t *api.Target) ([]string, error) { fileClient := t.FileClient() numFiles := len(a.Config.FileGetFile) files := make([]string, 0, numFiles) errs := make([]error, 0, numFiles) for _, f := range a.Config.FileGetFile { - fs, err := a.fileGet(ctx, t, fileClient, f) + fs, err := a.fileGetPath(ctx, t, fileClient, f) if err != nil { errs = append(errs, err) continue @@ -122,7 +123,7 @@ func (a *App) FileGet(ctx context.Context, t *api.Target) ([]string, error) { return files, nil } -func (a *App) fileGet(ctx context.Context, t *api.Target, fileClient file.FileClient, path string) ([]string, error) { +func (a *App) fileGetPath(ctx context.Context, t *api.Target, fileClient file.FileClient, path string) ([]string, error) { files := make([]string, 0) isDir, err := a.isDir(ctx, fileClient, path) if err != nil { @@ -134,7 +135,7 @@ func (a *App) fileGet(ctx context.Context, t *api.Target, fileClient file.FileCl return nil, err } for _, si := range r.Stats { - f, err := a.fileGet(ctx, t, fileClient, si.Path) + f, err := a.fileGetPath(ctx, t, fileClient, si.Path) if err != nil { return nil, err } diff --git a/app/filePut.go b/app/filePut.go index 1eca62f..d24337e 100644 --- a/app/filePut.go +++ b/app/filePut.go @@ -19,7 +19,6 @@ import ( "github.com/openconfig/gnoi/file" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" ) const ( @@ -90,32 +89,7 @@ func (a *App) RunEFilePut(cmd *cobra.Command, args []string) error { a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &filePutResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - } - return - } - defer t.Close() - filename, err := a.FilePut(ctx, t) - responseChan <- &filePutResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - file: filename, - } - }(t) + go a.filePutRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) @@ -140,6 +114,33 @@ func (a *App) RunEFilePut(cmd *cobra.Command, args []string) error { return a.handleErrs(errs) } +func (a *App) filePutRequest(ctx context.Context, t *api.Target, rspCh chan<- *filePutResponse) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &filePutResponse{ + TargetError: TargetError{ + TargetName: t.Config.Address, + Err: err, + }, + } + return + } + defer t.Close() + filename, err := a.FilePut(ctx, t) + rspCh <- &filePutResponse{ + TargetError: TargetError{ + TargetName: t.Config.Address, + Err: err, + }, + file: filename, + } +} + func (a *App) FilePut(ctx context.Context, t *api.Target) ([]string, error) { numFiles := len(a.Config.FilePutFile) @@ -218,7 +219,7 @@ func (a *App) filePut(ctx context.Context, t *api.Target, fileClient file.FileCl return err } - a.printMsg(t.Config.Name, req) + a.printProtoMsg(t.Config.Name, req) err = stream.Send(req) if err != nil { return err @@ -266,12 +267,12 @@ func (a *App) filePut(ctx context.Context, t *api.Target, fileClient file.FileCl if err != nil { return err } - a.printMsg(t.Config.Name, reqHash) + a.printProtoMsg(t.Config.Name, reqHash) err = stream.Send(reqHash) if err != nil { return err } rsp, err := stream.CloseAndRecv() - a.printMsg(t.Config.Name, rsp) + a.printProtoMsg(t.Config.Name, rsp) return err } diff --git a/app/fileRemove.go b/app/fileRemove.go index 1df7344..0ee295e 100644 --- a/app/fileRemove.go +++ b/app/fileRemove.go @@ -9,7 +9,6 @@ import ( "github.com/openconfig/gnoi/file" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" ) type fileRemoveResponse struct { @@ -38,32 +37,7 @@ func (a *App) RunEFileRemove(cmd *cobra.Command, args []string) error { a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &fileRemoveResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - } - return - } - defer t.Close() - filename, err := a.FileRemove(ctx, t) - responseChan <- &fileRemoveResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - file: filename, - } - }(t) + go a.fileRemoveRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) @@ -88,6 +62,33 @@ func (a *App) RunEFileRemove(cmd *cobra.Command, args []string) error { return a.handleErrs(errs) } +func (a *App) fileRemoveRequest(ctx context.Context, t *api.Target, rspCh chan<- *fileRemoveResponse) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &fileRemoveResponse{ + TargetError: TargetError{ + TargetName: t.Config.Address, + Err: err, + }, + } + return + } + defer t.Close() + filename, err := a.FileRemove(ctx, t) + rspCh <- &fileRemoveResponse{ + TargetError: TargetError{ + TargetName: t.Config.Address, + Err: err, + }, + file: filename, + } +} + func (a *App) FileRemove(ctx context.Context, t *api.Target) ([]string, error) { fileClient := t.FileClient() errs := make([]string, 0, len(a.Config.FileRemovePath)) diff --git a/app/fileStat.go b/app/fileStat.go index d9ed14f..fda39ba 100644 --- a/app/fileStat.go +++ b/app/fileStat.go @@ -16,7 +16,6 @@ import ( "github.com/openconfig/gnoi/file" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" "google.golang.org/protobuf/encoding/prototext" ) @@ -53,32 +52,7 @@ func (a *App) RunEFileStat(cmd *cobra.Command, args []string) error { a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &fileStatResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - } - return - } - defer t.Close() - rsp, err := a.FileStat(ctx, t) - responseChan <- &fileStatResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - rsp: rsp, - } - }(t) + go a.fileStatRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) @@ -115,6 +89,33 @@ func (a *App) RunEFileStat(cmd *cobra.Command, args []string) error { return a.handleErrs(errs) } +func (a *App) fileStatRequest(ctx context.Context, t *api.Target, rspCh chan<- *fileStatResponse) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &fileStatResponse{ + TargetError: TargetError{ + TargetName: t.Config.Address, + Err: err, + }, + } + return + } + defer t.Close() + rsp, err := a.FileStat(ctx, t) + rspCh <- &fileStatResponse{ + TargetError: TargetError{ + TargetName: t.Config.Address, + Err: err, + }, + rsp: rsp, + } +} + func (a *App) FileStat(ctx context.Context, t *api.Target) ([]*fileStatInfo, error) { fileClient := file.NewFileClient(t.Conn()) rsps := make([]*fileStatInfo, 0, len(a.Config.FileStatPath)) @@ -130,13 +131,13 @@ func (a *App) FileStat(ctx context.Context, t *api.Target) ([]*fileStatInfo, err func (a *App) fileStat(ctx context.Context, t *api.Target, fileClient file.FileClient, path string) ([]*fileStatInfo, error) { req := &file.StatRequest{Path: path} - a.printMsg(t.Config.Name, req) + a.printProtoMsg(t.Config.Name, req) r, err := fileClient.Stat(ctx, req) if err != nil { return nil, fmt.Errorf("%q file %q stat err: %v", t.Config.Address, path, err) } a.Logger.Debugf("%q File Stat Response:\n%s", t.Config.Address, prototext.Format(r)) - a.printMsg(t.Config.Name, r) + a.printProtoMsg(t.Config.Name, r) rsps := make([]*fileStatInfo, 0, len(r.Stats)) for _, si := range r.Stats { isDir, err := a.isDir(ctx, fileClient, si.Path) diff --git a/app/fileTransfer.go b/app/fileTransfer.go index 22bb3ad..eba4b2f 100644 --- a/app/fileTransfer.go +++ b/app/fileTransfer.go @@ -13,7 +13,6 @@ import ( "github.com/openconfig/gnoi/types" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" ) type fileTransferResponse struct { @@ -43,25 +42,7 @@ func (a *App) RunEFileTransfer(cmd *cobra.Command, args []string) error { responseChan := make(chan *fileTransferResponse, numTargets) a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &fileTransferResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - } - return - } - defer t.Close() - responseChan <- a.FileTransfer(ctx, t) - }(t) + go a.fileTransferRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) @@ -78,12 +59,32 @@ func (a *App) RunEFileTransfer(cmd *cobra.Command, args []string) error { result = append(result, rsp) } for _, r := range result { - a.printMsg(r.TargetName, r.rsp) + a.printProtoMsg(r.TargetName, r.rsp) } fmt.Print(a.transferTable(result)) return a.handleErrs(errs) } +func (a *App) fileTransferRequest(ctx context.Context, t *api.Target, rspCh chan<- *fileTransferResponse) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &fileTransferResponse{ + TargetError: TargetError{ + TargetName: t.Config.Address, + Err: err, + }, + } + return + } + defer t.Close() + rspCh <- a.FileTransfer(ctx, t) +} + func (a *App) FileTransfer(ctx context.Context, t *api.Target) *fileTransferResponse { rd, err := a.transferFileRemoteDownload() if err != nil { diff --git a/app/healthzAck.go b/app/healthzAck.go index dc7bab0..ff96db4 100644 --- a/app/healthzAck.go +++ b/app/healthzAck.go @@ -8,7 +8,6 @@ import ( "github.com/openconfig/gnoi/healthz" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" "github.com/karimra/gnoic/api" ghealthz "github.com/karimra/gnoic/api/healthz" @@ -41,25 +40,7 @@ func (a *App) RunEHealthzAck(cmd *cobra.Command, args []string) error { a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &healthzAckResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - } - return - } - defer t.Close() - responseChan <- a.HealthAck(ctx, t) - }(t) + go a.HealthAckRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) @@ -73,12 +54,11 @@ func (a *App) RunEHealthzAck(cmd *cobra.Command, args []string) error { errs = append(errs, wErr) continue } + a.printProtoMsg(rsp.TargetName, rsp.rsp) result = append(result, rsp) } for _, r := range result { - fmt.Printf("target %q:\n", r.TargetName) - a.printMsg(r.TargetName, r.rsp) switch a.Config.Format { case "json": b, err := json.MarshalIndent(r.rsp, "", " ") @@ -93,6 +73,26 @@ func (a *App) RunEHealthzAck(cmd *cobra.Command, args []string) error { return a.handleErrs(errs) } +func (a *App) HealthAckRequest(ctx context.Context, t *api.Target, rspCh chan<- *healthzAckResponse) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &healthzAckResponse{ + TargetError: TargetError{ + TargetName: t.Config.Address, + Err: err, + }, + } + return + } + defer t.Close() + rspCh <- a.HealthAck(ctx, t) +} + func (a *App) HealthAck(ctx context.Context, t *api.Target) *healthzAckResponse { opts := []ghealthz.HealthzOption{ ghealthz.Path(a.Config.HealthzAckPath), @@ -107,7 +107,7 @@ func (a *App) HealthAck(ctx context.Context, t *api.Target) *healthzAckResponse }, } } - a.printMsg(t.Config.Name, req) + a.printProtoMsg(t.Config.Name, req) hc := healthz.NewHealthzClient(t.Conn()) rsp, err := hc.Acknowledge(ctx, req) return &healthzAckResponse{ diff --git a/app/healthzArtifact.go b/app/healthzArtifact.go index d34058c..5429924 100644 --- a/app/healthzArtifact.go +++ b/app/healthzArtifact.go @@ -10,7 +10,6 @@ import ( log "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" "google.golang.org/protobuf/encoding/prototext" "github.com/karimra/gnoic/api" @@ -43,25 +42,7 @@ func (a *App) RunEHealthzArtifact(cmd *cobra.Command, args []string) error { a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &healthzArtifactResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - } - return - } - defer t.Close() - responseChan <- a.HealthArtifact(ctx, t) - }(t) + go a.HealthArtifactRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) @@ -79,11 +60,31 @@ func (a *App) RunEHealthzArtifact(cmd *cobra.Command, args []string) error { } for _, r := range result { - a.printMsg(r.TargetName, r.rsp) + a.printProtoMsg(r.TargetName, r.rsp) } return a.handleErrs(errs) } +func (a *App) HealthArtifactRequest(ctx context.Context, t *api.Target, rspCh chan<- *healthzArtifactResponse) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &healthzArtifactResponse{ + TargetError: TargetError{ + TargetName: t.Config.Address, + Err: err, + }, + } + return + } + defer t.Close() + rspCh <- a.HealthArtifact(ctx, t) +} + func (a *App) HealthArtifact(ctx context.Context, t *api.Target) *healthzArtifactResponse { opts := []ghealthz.HealthzOption{ ghealthz.ID(a.Config.HealthzArtifactID), @@ -97,7 +98,7 @@ func (a *App) HealthArtifact(ctx context.Context, t *api.Target) *healthzArtifac }, } } - a.printMsg(t.Config.Name, req) + a.printProtoMsg(t.Config.Name, req) hc := healthz.NewHealthzClient(t.Conn()) artifactStream, err := hc.Artifact(ctx, req) if err != nil { @@ -203,6 +204,5 @@ func (a *App) handleProtoArtifact(targetName string, h *healthz.ArtifactResponse id := h.Header.GetId() log.Infof("%s: received proto header for artifactID: %s", targetName, id) fmt.Println(prototext.Format(h.Header)) - // return nil } diff --git a/app/healthzCheck.go b/app/healthzCheck.go index 92dcb99..23b31bd 100644 --- a/app/healthzCheck.go +++ b/app/healthzCheck.go @@ -11,7 +11,6 @@ import ( "github.com/openconfig/gnoi/healthz" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" "github.com/karimra/gnoic/api" ghealthz "github.com/karimra/gnoic/api/healthz" @@ -45,25 +44,7 @@ func (a *App) RunEHealthzCheck(cmd *cobra.Command, args []string) error { a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &healthzCheckResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - } - return - } - defer t.Close() - responseChan <- a.HealthzCheck(ctx, t) - }(t) + go a.HealthzCheckRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) @@ -77,12 +58,12 @@ func (a *App) RunEHealthzCheck(cmd *cobra.Command, args []string) error { errs = append(errs, wErr) continue } + a.printProtoMsg(rsp.TargetName, rsp.rsp) result = append(result, rsp) } for _, r := range result { - fmt.Printf("target %q:\n", r.TargetName) - a.printMsg(r.TargetName, r.rsp) + switch a.Config.Format { case "json": b, err := json.MarshalIndent(r.rsp, "", " ") @@ -101,6 +82,26 @@ func (a *App) RunEHealthzCheck(cmd *cobra.Command, args []string) error { return a.handleErrs(errs) } +func (a *App) HealthzCheckRequest(ctx context.Context, t *api.Target, rspCh chan<- *healthzCheckResponse) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &healthzCheckResponse{ + TargetError: TargetError{ + TargetName: t.Config.Address, + Err: err, + }, + } + return + } + defer t.Close() + rspCh <- a.HealthzCheck(ctx, t) +} + func (a *App) HealthzCheck(ctx context.Context, t *api.Target) *healthzCheckResponse { opts := []ghealthz.HealthzOption{ ghealthz.Path(a.Config.HealthzCheckPath), @@ -115,7 +116,7 @@ func (a *App) HealthzCheck(ctx context.Context, t *api.Target) *healthzCheckResp }, } } - a.printMsg(t.Config.Name, req) + a.printProtoMsg(t.Config.Name, req) hc := healthz.NewHealthzClient(t.Conn()) rsp, err := hc.Check(ctx, req) return &healthzCheckResponse{ diff --git a/app/healthzGet.go b/app/healthzGet.go index 7481fd8..2218f51 100644 --- a/app/healthzGet.go +++ b/app/healthzGet.go @@ -10,7 +10,6 @@ import ( "github.com/openconfig/gnoi/healthz" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" "google.golang.org/protobuf/encoding/prototext" "github.com/karimra/gnoic/api" @@ -52,25 +51,7 @@ func (a *App) RunEHealthzGet(cmd *cobra.Command, args []string) error { a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &healthzGetResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - } - return - } - defer t.Close() - responseChan <- a.HealthzGet(ctx, t) - }(t) + go a.HealthzGetRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) @@ -84,12 +65,12 @@ func (a *App) RunEHealthzGet(cmd *cobra.Command, args []string) error { errs = append(errs, wErr) continue } + a.printProtoMsg(rsp.TargetName, rsp.rsp) result = append(result, rsp) } for _, r := range result { - fmt.Printf("target %q:\n", r.TargetName) - a.printMsg(r.TargetName, r.rsp) + switch a.Config.Format { case "json": b, err := json.MarshalIndent(r.rsp, "", " ") @@ -104,6 +85,26 @@ func (a *App) RunEHealthzGet(cmd *cobra.Command, args []string) error { return a.handleErrs(errs) } +func (a *App) HealthzGetRequest(ctx context.Context, t *api.Target, rspCh chan<- *healthzGetResponse) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &healthzGetResponse{ + TargetError: TargetError{ + TargetName: t.Config.Address, + Err: err, + }, + } + return + } + defer t.Close() + rspCh <- a.HealthzGet(ctx, t) +} + func (a *App) HealthzGet(ctx context.Context, t *api.Target) *healthzGetResponse { opts := []ghealthz.HealthzOption{ ghealthz.Path(a.Config.HealthzGetPath), @@ -117,7 +118,7 @@ func (a *App) HealthzGet(ctx context.Context, t *api.Target) *healthzGetResponse }, } } - a.printMsg(t.Config.Name, req) + a.printProtoMsg(t.Config.Name, req) hc := healthz.NewHealthzClient(t.Conn()) rsp, err := hc.Get(ctx, req) return &healthzGetResponse{ diff --git a/app/healthzList.go b/app/healthzList.go index 316453c..25000db 100644 --- a/app/healthzList.go +++ b/app/healthzList.go @@ -11,7 +11,6 @@ import ( "github.com/openconfig/gnoi/healthz" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" "github.com/karimra/gnoic/api" ghealthz "github.com/karimra/gnoic/api/healthz" @@ -45,25 +44,7 @@ func (a *App) RunEHealthzList(cmd *cobra.Command, args []string) error { a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &healthzListResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - } - return - } - defer t.Close() - responseChan <- a.HealthzList(ctx, t) - }(t) + go a.HealthzListRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) @@ -81,8 +62,7 @@ func (a *App) RunEHealthzList(cmd *cobra.Command, args []string) error { } for _, r := range result { - fmt.Printf("target %q:\n", r.TargetName) - a.printMsg(r.TargetName, r.rsp) + a.printProtoMsg(r.TargetName, r.rsp) switch a.Config.Format { case "json": b, err := json.MarshalIndent(r.rsp, "", " ") @@ -101,6 +81,26 @@ func (a *App) RunEHealthzList(cmd *cobra.Command, args []string) error { return a.handleErrs(errs) } +func (a *App) HealthzListRequest(ctx context.Context, t *api.Target, rspCh chan<- *healthzListResponse) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &healthzListResponse{ + TargetError: TargetError{ + TargetName: t.Config.Address, + Err: err, + }, + } + return + } + defer t.Close() + rspCh <- a.HealthzList(ctx, t) +} + func (a *App) HealthzList(ctx context.Context, t *api.Target) *healthzListResponse { opts := []ghealthz.HealthzOption{ ghealthz.Path(a.Config.HealthzListPath), @@ -115,7 +115,7 @@ func (a *App) HealthzList(ctx context.Context, t *api.Target) *healthzListRespon }, } } - a.printMsg(t.Config.Name, req) + a.printProtoMsg(t.Config.Name, req) hc := healthz.NewHealthzClient(t.Conn()) rsp, err := hc.List(ctx, req) return &healthzListResponse{ diff --git a/app/osActivate.go b/app/osActivate.go index e82471b..da67c77 100644 --- a/app/osActivate.go +++ b/app/osActivate.go @@ -9,7 +9,6 @@ import ( gnoios "github.com/openconfig/gnoi/os" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" ) type osActivateResponse struct { @@ -30,6 +29,7 @@ func (a *App) InitOSActivateFlags(cmd *cobra.Command) { } func (a *App) PreRunEOSActivate(cmd *cobra.Command, args []string) error { return nil } + func (a *App) RunEOSActivate(cmd *cobra.Command, args []string) error { targets, err := a.GetTargets() if err != nil { @@ -41,32 +41,7 @@ func (a *App) RunEOSActivate(cmd *cobra.Command, args []string) error { a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &osActivateResponse{ - TargetError: TargetError{ - TargetName: t.Config.Name, - Err: err, - }, - } - return - } - defer t.Close() - rsp, err := a.OsActivate(ctx, t) - responseChan <- &osActivateResponse{ - TargetError: TargetError{ - TargetName: t.Config.Name, - Err: err, - }, - rsp: rsp, - } - }(t) + go a.OsActivateRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) @@ -80,7 +55,7 @@ func (a *App) RunEOSActivate(cmd *cobra.Command, args []string) error { continue } result = append(result, rsp) - a.printMsg(rsp.TargetName, rsp.rsp) + a.printProtoMsg(rsp.TargetName, rsp.rsp) } for _, r := range result { a.Logger.Infof("target %q activate response %q", r.TargetName, r.rsp) @@ -88,6 +63,33 @@ func (a *App) RunEOSActivate(cmd *cobra.Command, args []string) error { return a.handleErrs(errs) } +func (a *App) OsActivateRequest(ctx context.Context, t *api.Target, rspCh chan<- *osActivateResponse) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &osActivateResponse{ + TargetError: TargetError{ + TargetName: t.Config.Name, + Err: err, + }, + } + return + } + defer t.Close() + rsp, err := a.OsActivate(ctx, t) + rspCh <- &osActivateResponse{ + TargetError: TargetError{ + TargetName: t.Config.Name, + Err: err, + }, + rsp: rsp, + } +} + func (a *App) OsActivate(ctx context.Context, t *api.Target) (*gnoios.ActivateResponse, error) { req, err := gos.NewActivateRequest( gos.Version(a.Config.OsActivateVersion), @@ -97,6 +99,6 @@ func (a *App) OsActivate(ctx context.Context, t *api.Target) (*gnoios.ActivateRe if err != nil { return nil, err } - a.printMsg(t.Config.Name, req) + a.printProtoMsg(t.Config.Name, req) return gnoios.NewOSClient(t.Conn()).Activate(ctx, req) } diff --git a/app/osInstall.go b/app/osInstall.go index 707ee8c..de1cff9 100644 --- a/app/osInstall.go +++ b/app/osInstall.go @@ -14,7 +14,6 @@ import ( gnoios "github.com/openconfig/gnoi/os" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" ) type osInstallResponse struct { @@ -57,43 +56,46 @@ func (a *App) RunEOSInstall(cmd *cobra.Command, args []string) error { a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &osInstallResponse{ - TargetError: TargetError{ - TargetName: t.Config.Name, - Err: err, - }, - } - return - } - defer t.Close() - a.Logger.Infof("starting install RPC") - err = a.OsInstall(ctx, t) - responseChan <- &osInstallResponse{ - TargetError: TargetError{ - TargetName: t.Config.Name, - Err: err, - }, - } - }(t) + go a.OsInstallRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) for rsp := range responseChan { if rsp.Err != nil { - fmt.Printf("%+v\n", rsp) + a.Logger.Errorf("%+v", rsp) } } return nil } +func (a *App) OsInstallRequest(ctx context.Context, t *api.Target, rspCh chan<- *osInstallResponse) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &osInstallResponse{ + TargetError: TargetError{ + TargetName: t.Config.Name, + Err: err, + }, + } + return + } + defer t.Close() + a.Logger.Infof("%s: starting install RPC", t.Config.Name) + err = a.OsInstall(ctx, t) + rspCh <- &osInstallResponse{ + TargetError: TargetError{ + TargetName: t.Config.Name, + Err: err, + }, + } + +} + func (a *App) OsInstall(ctx context.Context, t *api.Target) error { // start stream osc := gnoios.NewOSClient(t.Conn()) @@ -109,7 +111,7 @@ func (a *App) OsInstall(ctx context.Context, t *api.Target) error { if err != nil { return err } - a.printMsg(t.Config.Name, req) + a.printProtoMsg(t.Config.Name, req) err = osInstallClient.Send(req) if err != nil { return err @@ -122,7 +124,7 @@ RCV: return err } a.Logger.Debugf("target %q: OS Install stream got: %+v", t.Config.Name, rsp) - a.printMsg(t.Config.Name, rsp) + a.printProtoMsg(t.Config.Name, rsp) switch rsp := rsp.GetResponse().(type) { case *gnoios.InstallResponse_TransferReady: err = a.osInstallTransferContent(ctx, t, osInstallClient) @@ -170,7 +172,7 @@ func (a *App) osInstallTransferContent(ctx context.Context, t *api.Target, osic errCh <- err return } - a.printMsg(t.Config.Name, rsp) + a.printProtoMsg(t.Config.Name, rsp) switch rsp := rsp.GetResponse().(type) { case *gnoios.InstallResponse_InstallError: a.Logger.Errorf("target %q Install Content Transfer RPC failed: %v: %v", t.Config.Name, rsp.InstallError.GetType(), rsp.InstallError.GetDetail()) diff --git a/app/osVerify.go b/app/osVerify.go index 5a85226..432ebb9 100644 --- a/app/osVerify.go +++ b/app/osVerify.go @@ -11,7 +11,6 @@ import ( gnoios "github.com/openconfig/gnoi/os" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" "github.com/karimra/gnoic/api" gos "github.com/karimra/gnoic/api/os" @@ -42,32 +41,7 @@ func (a *App) RunEOSVerify(cmd *cobra.Command, args []string) error { a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &osVerifyResponse{ - TargetError: TargetError{ - TargetName: t.Config.Name, - Err: err, - }, - } - return - } - defer t.Close() - rsp, err := a.OsVerify(ctx, t) - responseChan <- &osVerifyResponse{ - TargetError: TargetError{ - TargetName: t.Config.Name, - Err: err, - }, - rsp: rsp, - } - }(t) + go a.OsVerifyRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) @@ -81,7 +55,7 @@ func (a *App) RunEOSVerify(cmd *cobra.Command, args []string) error { continue } result = append(result, rsp) - a.printMsg(rsp.TargetName, rsp.rsp) + a.printProtoMsg(rsp.TargetName, rsp.rsp) } switch a.Config.Format { default: @@ -104,6 +78,33 @@ func (a *App) RunEOSVerify(cmd *cobra.Command, args []string) error { return a.handleErrs(errs) } +func (a *App) OsVerifyRequest(ctx context.Context, t *api.Target, rspCh chan<- *osVerifyResponse) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &osVerifyResponse{ + TargetError: TargetError{ + TargetName: t.Config.Name, + Err: err, + }, + } + return + } + defer t.Close() + rsp, err := a.OsVerify(ctx, t) + rspCh <- &osVerifyResponse{ + TargetError: TargetError{ + TargetName: t.Config.Name, + Err: err, + }, + rsp: rsp, + } +} + func (a *App) OsVerify(ctx context.Context, t *api.Target) (*gnoios.VerifyResponse, error) { return gnoios.NewOSClient(t.Conn()).Verify(ctx, gos.NewOSVerifyRequest()) } diff --git a/app/server.go b/app/server.go index f14e257..8038e5e 100644 --- a/app/server.go +++ b/app/server.go @@ -71,7 +71,7 @@ func (a *App) RunEServer(cmd *cobra.Command, args []string) error { } file.RegisterFileServer(fileServer.s, fileServer) reflection.Register(fileServer.s) - ctx, cancel := context.WithCancel(a.ctx) + ctx, cancel := context.WithCancel(cmd.Context()) go func() { err = fileServer.s.Serve(l) if err != nil { diff --git a/app/services.go b/app/services.go index cf11034..992c07e 100644 --- a/app/services.go +++ b/app/services.go @@ -10,7 +10,6 @@ import ( "github.com/karimra/gnoic/api" "github.com/olekukonko/tablewriter" "github.com/spf13/cobra" - "google.golang.org/grpc/metadata" reflectpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha" ) @@ -19,6 +18,14 @@ type reflectionResponse struct { rsp *reflectpb.ServerReflectionResponse } +func (r *reflectionResponse) Target() string { + return r.TargetName +} + +func (r *reflectionResponse) Response() any { + return r.rsp +} + func (a *App) RunEServices(cmd *cobra.Command, args []string) error { targets, err := a.GetTargets() if err != nil { @@ -34,7 +41,7 @@ func (a *App) RunEServices(cmd *cobra.Command, args []string) error { a.wg.Wait() close(responseChan) errs := make([]error, 0, numTargets) - result := make([]*reflectionResponse, 0, numTargets) + result := make([]TargetResponse, 0, numTargets) for rsp := range responseChan { if rsp.Err != nil { @@ -44,28 +51,33 @@ func (a *App) RunEServices(cmd *cobra.Command, args []string) error { continue } result = append(result, rsp) - a.printMsg(rsp.TargetName, rsp.rsp) + a.printProtoMsg(rsp.TargetName, rsp.rsp) } a.printCMDOutput(result, a.reflectionServicesTable) return a.handleErrs(errs) } -func (a *App) reflectionServicesTable(rs []*reflectionResponse) string { +func (a *App) reflectionServicesTable(rs []TargetResponse) string { targetTabData := make([][]string, 0, len(rs)) sort.Slice(rs, func(i, j int) bool { - return rs[i].TargetName < rs[j].TargetName + return rs[i].Target() < rs[j].Target() }) for _, rsp := range rs { - switch r := rsp.rsp.MessageResponse.(type) { - case *reflectpb.ServerReflectionResponse_ListServicesResponse: - for _, srv := range r.ListServicesResponse.GetService() { - targetTabData = append(targetTabData, []string{ - rsp.TargetName, - srv.GetName(), - }) + switch r := rsp.Response().(type) { + case *reflectpb.ServerReflectionResponse: + switch r := r.MessageResponse.(type) { + case *reflectpb.ServerReflectionResponse_ListServicesResponse: + for _, srv := range r.ListServicesResponse.GetService() { + targetTabData = append(targetTabData, []string{ + rsp.Target(), + srv.GetName(), + }) + } + default: + a.Logger.Printf("%s: unexpected message type: %T", rsp.Target(), rsp.Response()) } default: - a.Logger.Printf("%s: unexpected message type: %T", rsp.TargetName, rsp.rsp) + a.Logger.Printf("%s: unexpected message type: %T", rsp.Target(), rsp.Response()) } } @@ -80,9 +92,9 @@ func (a *App) reflectionServicesTable(rs []*reflectionResponse) string { func (a *App) reflectionServicesRequest(ctx context.Context, t *api.Target, rspCh chan<- *reflectionResponse) { defer a.wg.Done() + ctx = t.AppendMetadata(ctx) ctx, cancel := context.WithCancel(ctx) defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) if err != nil { @@ -130,19 +142,19 @@ func (a *App) reflectionServicesRequest(ctx context.Context, t *api.Target, rspC } } -func (a *App) printCMDOutput(rs []*reflectionResponse, fn func([]*reflectionResponse) string) { +func (a *App) printCMDOutput(rs []TargetResponse, fn func([]TargetResponse) string) { switch a.Config.Format { default: fmt.Println(fn(rs)) case "json": for _, r := range rs { tRsp := targetResponse{ - Target: r.TargetName, - Response: r.rsp, + Target: r.Target(), + Response: r.Response(), } b, err := json.MarshalIndent(tRsp, "", " ") if err != nil { - a.Logger.Errorf("failed to marshal Target response from %q: %v", r.TargetName, err) + a.Logger.Errorf("failed to marshal Target response from %q: %v", r.Target(), err) continue } fmt.Println(string(b)) diff --git a/app/system.go b/app/system.go index 509c170..51c3177 100644 --- a/app/system.go +++ b/app/system.go @@ -1,16 +1,9 @@ package app -import ( - "fmt" - - "github.com/spf13/cobra" - "github.com/spf13/pflag" -) - -func (a *App) InitSystemFlags(cmd *cobra.Command) { - cmd.ResetFlags() - // - cmd.LocalFlags().VisitAll(func(flag *pflag.Flag) { - a.Config.FileConfig.BindPFlag(fmt.Sprintf("%s-%s", cmd.Name(), flag.Name), flag) - }) -} +// func (a *App) InitSystemFlags(cmd *cobra.Command) { +// cmd.ResetFlags() +// // +// cmd.LocalFlags().VisitAll(func(flag *pflag.Flag) { +// a.Config.FileConfig.BindPFlag(fmt.Sprintf("%s-%s", cmd.Name(), flag.Name), flag) +// }) +// } diff --git a/app/systemCancelReboot.go b/app/systemCancelReboot.go index 3a03485..f0a8e6d 100644 --- a/app/systemCancelReboot.go +++ b/app/systemCancelReboot.go @@ -10,7 +10,6 @@ import ( "github.com/openconfig/gnoi/types" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" "google.golang.org/protobuf/encoding/prototext" ) @@ -41,27 +40,7 @@ func (a *App) RunESystemCancelReboot(cmd *cobra.Command, args []string) error { responseChan := make(chan *TargetError, numTargets) a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target, subcomponents []*types.Path) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &TargetError{ - TargetName: t.Config.Address, - Err: err, - } - return - } - defer t.Close() - err := a.SystemCancelReboot(ctx, t, subcomponents) - responseChan <- &TargetError{ - TargetName: t.Config.Address, - Err: err, - } - }(t, subcomponents) + go a.systemCancelRebootRequest(cmd.Context(), t, subcomponents, responseChan) } a.wg.Wait() close(responseChan) @@ -78,13 +57,35 @@ func (a *App) RunESystemCancelReboot(cmd *cobra.Command, args []string) error { return a.handleErrs(errs) } +func (a *App) systemCancelRebootRequest(ctx context.Context, t *api.Target, subcomponents []*types.Path, rspCh chan<- *TargetError) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &TargetError{ + TargetName: t.Config.Address, + Err: err, + } + return + } + defer t.Close() + err = a.SystemCancelReboot(ctx, t, subcomponents) + rspCh <- &TargetError{ + TargetName: t.Config.Address, + Err: err, + } +} + func (a *App) SystemCancelReboot(ctx context.Context, t *api.Target, subcomponents []*types.Path) error { req := &system.CancelRebootRequest{ Message: a.Config.SystemCancelRebootMessage, Subcomponents: subcomponents, } a.Logger.Debugf("%q System CancelReboot Request: %s", t.Config.Address, prototext.Format(req)) - a.printMsg(t.Config.Name, req) + a.printProtoMsg(t.Config.Name, req) _, err := t.SystemClient().CancelReboot(ctx, req) if err != nil { return err diff --git a/app/systemKillProcess.go b/app/systemKillProcess.go index fbf8fdc..d2b598b 100644 --- a/app/systemKillProcess.go +++ b/app/systemKillProcess.go @@ -7,7 +7,6 @@ import ( "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" "github.com/karimra/gnoic/api" gsystem "github.com/karimra/gnoic/api/system" @@ -52,27 +51,7 @@ func (a *App) RunESystemKillProcess(cmd *cobra.Command, args []string) error { responseChan := make(chan *TargetError, numTargets) a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &TargetError{ - TargetName: t.Config.Address, - Err: err, - } - return - } - defer t.Close() - err := a.SystemKillProcess(ctx, t) - responseChan <- &TargetError{ - TargetName: t.Config.Address, - Err: err, - } - }(t) + go a.systemKillProcessRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) @@ -89,6 +68,28 @@ func (a *App) RunESystemKillProcess(cmd *cobra.Command, args []string) error { return a.handleErrs(errs) } +func (a *App) systemKillProcessRequest(ctx context.Context, t *api.Target, rspCh chan<- *TargetError) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &TargetError{ + TargetName: t.Config.Address, + Err: err, + } + return + } + defer t.Close() + err = a.SystemKillProcess(ctx, t) + rspCh <- &TargetError{ + TargetName: t.Config.Address, + Err: err, + } +} + func (a *App) SystemKillProcess(ctx context.Context, t *api.Target) error { req, err := gsystem.NewSystemKillProcessRequest( gsystem.PID(a.Config.SystemKillProcessPID), diff --git a/app/systemPing.go b/app/systemPing.go index 4ff0f8b..9541b98 100644 --- a/app/systemPing.go +++ b/app/systemPing.go @@ -15,7 +15,6 @@ import ( "github.com/openconfig/gnoi/system" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" "google.golang.org/protobuf/encoding/prototext" ) @@ -69,27 +68,7 @@ func (a *App) RunESystemPing(cmd *cobra.Command, args []string) error { a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &TargetError{ - TargetName: t.Config.Address, - Err: err, - } - return - } - defer t.Close() - err := a.SystemPing(ctx, t) - responseChan <- &TargetError{ - TargetName: t.Config.Address, - Err: err, - } - }(t) + go a.systemPingRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) @@ -106,6 +85,28 @@ func (a *App) RunESystemPing(cmd *cobra.Command, args []string) error { return a.handleErrs(errs) } +func (a *App) systemPingRequest(ctx context.Context, t *api.Target, rspCh chan<- *TargetError) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &TargetError{ + TargetName: t.Config.Address, + Err: err, + } + return + } + defer t.Close() + err = a.SystemPing(ctx, t) + rspCh <- &TargetError{ + TargetName: t.Config.Address, + Err: err, + } +} + func (a *App) SystemPing(ctx context.Context, t *api.Target) error { req, err := gsystem.NewSystemPingRequest( gsystem.Destination(a.Config.SystemPingDestination), @@ -122,7 +123,7 @@ func (a *App) SystemPing(ctx context.Context, t *api.Target) error { return err } a.Logger.Debugf("ping request:\n%s", prototext.Format(req)) - a.printMsg(t.Config.Name, req) + a.printProtoMsg(t.Config.Name, req) stream, err := t.SystemClient().Ping(ctx, req) if err != nil { a.Logger.Errorf("%q creating System Ping stream failed: %v", t.Config.Address, err) @@ -139,7 +140,7 @@ func (a *App) SystemPing(ctx context.Context, t *api.Target) error { return err } a.Logger.Debugf("ping response %s:\n%s", t.Config.Name, prototext.Format(rsp)) - a.printMsg(t.Config.Name, rsp) + a.printProtoMsg(t.Config.Name, rsp) a.printPingResponse(t.Config.Name, rsp) } return nil diff --git a/app/systemReboot.go b/app/systemReboot.go index 23a4182..375486c 100644 --- a/app/systemReboot.go +++ b/app/systemReboot.go @@ -11,7 +11,6 @@ import ( "github.com/openconfig/gnoi/types" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" ) func (a *App) InitSystemRebootFlags(cmd *cobra.Command) { @@ -60,27 +59,7 @@ func (a *App) RunESystemReboot(cmd *cobra.Command, args []string) error { responseChan := make(chan *TargetError, numTargets) a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target, subcomponents []*types.Path) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &TargetError{ - TargetName: t.Config.Address, - Err: err, - } - return - } - defer t.Close() - err := a.SystemReboot(ctx, t, subcomponents) - responseChan <- &TargetError{ - TargetName: t.Config.Address, - Err: err, - } - }(t, subcomponents) + go a.systemRebootRequest(cmd.Context(), t, subcomponents, responseChan) } a.wg.Wait() close(responseChan) @@ -97,6 +76,28 @@ func (a *App) RunESystemReboot(cmd *cobra.Command, args []string) error { return a.handleErrs(errs) } +func (a *App) systemRebootRequest(ctx context.Context, t *api.Target, subcomponents []*types.Path, rspCh chan<- *TargetError) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &TargetError{ + TargetName: t.Config.Address, + Err: err, + } + return + } + defer t.Close() + err = a.SystemReboot(ctx, t, subcomponents) + rspCh <- &TargetError{ + TargetName: t.Config.Address, + Err: err, + } +} + func (a *App) SystemReboot(ctx context.Context, t *api.Target, subcomponents []*types.Path) error { req := &system.RebootRequest{ Method: system.RebootMethod(system.RebootMethod_value[a.Config.SystemRebootMethod]), diff --git a/app/systemRebootStatus.go b/app/systemRebootStatus.go index 113c842..b6984c3 100644 --- a/app/systemRebootStatus.go +++ b/app/systemRebootStatus.go @@ -15,7 +15,6 @@ import ( "github.com/openconfig/gnoi/types" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" "google.golang.org/protobuf/encoding/prototext" ) @@ -50,32 +49,7 @@ func (a *App) RunESystemRebootStatus(cmd *cobra.Command, args []string) error { responseChan := make(chan *systemRebootStatusResponse, numTargets) a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target, subcomponents []*types.Path) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &systemRebootStatusResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - } - return - } - defer t.Close() - rsp, err := a.SystemRebootStatus(ctx, t, subcomponents) - responseChan <- &systemRebootStatusResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - rsp: rsp, - } - }(t, subcomponents) + go a.systemRebootStatusRequest(cmd.Context(), t, subcomponents, responseChan) } a.wg.Wait() close(responseChan) @@ -100,6 +74,33 @@ func (a *App) RunESystemRebootStatus(cmd *cobra.Command, args []string) error { return a.handleErrs(errs) } +func (a *App) systemRebootStatusRequest(ctx context.Context, t *api.Target, subcomponents []*types.Path, rspCh chan<- *systemRebootStatusResponse) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &systemRebootStatusResponse{ + TargetError: TargetError{ + TargetName: t.Config.Address, + Err: err, + }, + } + return + } + defer t.Close() + rsp, err := a.SystemRebootStatus(ctx, t, subcomponents) + rspCh <- &systemRebootStatusResponse{ + TargetError: TargetError{ + TargetName: t.Config.Address, + Err: err, + }, + rsp: rsp, + } +} + func (a *App) SystemRebootStatus(ctx context.Context, t *api.Target, subcomponents []*types.Path) (*system.RebootStatusResponse, error) { req := &system.RebootStatusRequest{ Subcomponents: subcomponents, diff --git a/app/systemSwitchControlProcessor.go b/app/systemSwitchControlProcessor.go index e55112d..5047851 100644 --- a/app/systemSwitchControlProcessor.go +++ b/app/systemSwitchControlProcessor.go @@ -14,7 +14,6 @@ import ( "github.com/openconfig/gnoi/system" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" ) type systemSwitchControlProcessorResponse struct { @@ -45,32 +44,7 @@ func (a *App) RunESystemSwitchControlProcessor(cmd *cobra.Command, args []string responseChan := make(chan *systemSwitchControlProcessorResponse, numTargets) a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &systemSwitchControlProcessorResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - } - return - } - defer t.Close() - rsp, err := a.SystemSwitchControlProcessor(ctx, t) - responseChan <- &systemSwitchControlProcessorResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - rsp: rsp, - } - }(t) + go a.systemSwitchControlProcessorRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) @@ -95,6 +69,33 @@ func (a *App) RunESystemSwitchControlProcessor(cmd *cobra.Command, args []string return a.handleErrs(errs) } +func (a *App) systemSwitchControlProcessorRequest(ctx context.Context, t *api.Target, rspCh chan<- *systemSwitchControlProcessorResponse) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &systemSwitchControlProcessorResponse{ + TargetError: TargetError{ + TargetName: t.Config.Address, + Err: err, + }, + } + return + } + defer t.Close() + rsp, err := a.SystemSwitchControlProcessor(ctx, t) + rspCh <- &systemSwitchControlProcessorResponse{ + TargetError: TargetError{ + TargetName: t.Config.Address, + Err: err, + }, + rsp: rsp, + } +} + func (a *App) SystemSwitchControlProcessor(ctx context.Context, t *api.Target) (*system.SwitchControlProcessorResponse, error) { p, err := utils.ParsePath(a.Config.SystemSwitchControlProcessorPath) if err != nil { @@ -103,12 +104,12 @@ func (a *App) SystemSwitchControlProcessor(ctx context.Context, t *api.Target) ( req := &system.SwitchControlProcessorRequest{ ControlProcessor: p, } - a.printMsg(t.Config.Name, req) + a.printProtoMsg(t.Config.Name, req) rsp, err := t.SystemClient().SwitchControlProcessor(ctx, req) if err != nil { return nil, err } - a.printMsg(t.Config.Name, rsp) + a.printProtoMsg(t.Config.Name, rsp) a.Logger.Infof("%q System SwitchControlProcessor Request successful", t.Config.Address) return rsp, nil } diff --git a/app/systemTime.go b/app/systemTime.go index 3d998db..7fce9e5 100644 --- a/app/systemTime.go +++ b/app/systemTime.go @@ -14,7 +14,6 @@ import ( "github.com/openconfig/gnoi/system" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" ) type systemTimeResponse struct { @@ -41,32 +40,7 @@ func (a *App) RunESystemTime(cmd *cobra.Command, args []string) error { responseChan := make(chan *systemTimeResponse, numTargets) a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &systemTimeResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - } - return - } - defer t.Close() - rsp, err := t.SystemClient().Time(ctx, gsystem.NewSystemTimeRequest()) - responseChan <- &systemTimeResponse{ - TargetError: TargetError{ - TargetName: t.Config.Address, - Err: err, - }, - rsp: rsp, - } - }(t) + go a.systemTimeRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) @@ -90,6 +64,33 @@ func (a *App) RunESystemTime(cmd *cobra.Command, args []string) error { return a.handleErrs(errs) } +func (a *App) systemTimeRequest(ctx context.Context, t *api.Target, rspCh chan<- *systemTimeResponse) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &systemTimeResponse{ + TargetError: TargetError{ + TargetName: t.Config.Address, + Err: err, + }, + } + return + } + defer t.Close() + rsp, err := t.SystemClient().Time(ctx, gsystem.NewSystemTimeRequest()) + rspCh <- &systemTimeResponse{ + TargetError: TargetError{ + TargetName: t.Config.Address, + Err: err, + }, + rsp: rsp, + } +} + func systemTimeTable(rsps []*systemTimeResponse) (string, error) { tabData := make([][]string, 0, len(rsps)) for _, rsp := range rsps { diff --git a/app/systemTraceRoute.go b/app/systemTraceRoute.go index 0549d92..24e55b7 100644 --- a/app/systemTraceRoute.go +++ b/app/systemTraceRoute.go @@ -15,7 +15,6 @@ import ( "github.com/openconfig/gnoi/system" "github.com/spf13/cobra" "github.com/spf13/pflag" - "google.golang.org/grpc/metadata" "google.golang.org/protobuf/encoding/prototext" ) @@ -70,27 +69,7 @@ func (a *App) RunESystemTraceRoute(cmd *cobra.Command, args []string) error { a.wg.Add(numTargets) for _, t := range targets { - go func(t *api.Target) { - defer a.wg.Done() - ctx, cancel := context.WithCancel(a.ctx) - defer cancel() - ctx = metadata.AppendToOutgoingContext(ctx, "username", *t.Config.Username, "password", *t.Config.Password) - - err = t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) - if err != nil { - responseChan <- &TargetError{ - TargetName: t.Config.Address, - Err: err, - } - return - } - defer t.Close() - err := a.SystemTraceRoute(ctx, t) - responseChan <- &TargetError{ - TargetName: t.Config.Address, - Err: err, - } - }(t) + go a.systemTraceRouteRequest(cmd.Context(), t, responseChan) } a.wg.Wait() close(responseChan) @@ -107,6 +86,28 @@ func (a *App) RunESystemTraceRoute(cmd *cobra.Command, args []string) error { return a.handleErrs(errs) } +func (a *App) systemTraceRouteRequest(ctx context.Context, t *api.Target, rspCh chan<- *TargetError) { + defer a.wg.Done() + ctx = t.AppendMetadata(ctx) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + err := t.CreateGrpcClient(ctx, a.createBaseDialOpts()...) + if err != nil { + rspCh <- &TargetError{ + TargetName: t.Config.Address, + Err: err, + } + return + } + defer t.Close() + err = a.SystemTraceRoute(ctx, t) + rspCh <- &TargetError{ + TargetName: t.Config.Address, + Err: err, + } +} + func (a *App) SystemTraceRoute(ctx context.Context, t *api.Target) error { req, err := gsystem.NewSystemTracerouteRequest( gsystem.Destination(a.Config.SystemTracerouteDestination), @@ -124,7 +125,7 @@ func (a *App) SystemTraceRoute(ctx context.Context, t *api.Target) error { return err } a.Logger.Debug(prototext.Format(req)) - a.printMsg(t.Config.Name, req) + a.printProtoMsg(t.Config.Name, req) stream, err := t.SystemClient().Traceroute(ctx, req) if err != nil { a.Logger.Errorf("creating System Traceroute stream failed: %v", err) @@ -140,7 +141,7 @@ func (a *App) SystemTraceRoute(ctx context.Context, t *api.Target) error { a.Logger.Errorf("rcv System Traceroute stream failed: %v", err) return err } - a.printMsg(t.Config.Name, rsp) + a.printProtoMsg(t.Config.Name, rsp) a.printTracerouteResponse(t.Config.Name, rsp) } return nil diff --git a/cmd/file.go b/cmd/file.go index 92e3c6f..4032960 100644 --- a/cmd/file.go +++ b/cmd/file.go @@ -14,7 +14,6 @@ func newFileCmd() *cobra.Command { SilenceUsage: true, } - gApp.InitFileFlags(cmd) cmd.AddCommand( newFileGetCmd(), newFileTransferCmd(), diff --git a/cmd/system.go b/cmd/system.go index 9639c09..4fad98f 100644 --- a/cmd/system.go +++ b/cmd/system.go @@ -11,7 +11,8 @@ func newSystemCmd() *cobra.Command { SilenceUsage: true, } - gApp.InitSystemFlags(cmd) + // no system level flags + cmd.AddCommand( newSystemPingCmd(), newSystemTracerouteCmd(),