Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Unified Diff: client/cmd/rpc/show.go

Issue 1587323003: client/cmd/rpc: RPC CLI (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/luci-go@discovery
Patch Set: fix Resolve, do not print package Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: client/cmd/rpc/show.go
diff --git a/client/cmd/rpc/show.go b/client/cmd/rpc/show.go
new file mode 100644
index 0000000000000000000000000000000000000000..dd89687b39f5f0393540cce1da587858c67738ab
--- /dev/null
+++ b/client/cmd/rpc/show.go
@@ -0,0 +1,156 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "net/url"
+ "os"
+ "strings"
+
+ "github.com/golang/protobuf/proto"
+ "github.com/maruel/subcommands"
+ "golang.org/x/net/context"
+
+ "github.com/luci/luci-go/common/proto/google/descriptor"
+ "github.com/luci/luci-go/server/discovery"
+)
+
+var cmdShow = &subcommands.Command{
+ UsageLine: `show [flags] <server> [name]
+
+ server: scheme (http or https) and hostname, e.g. "https://example.com".
+ A short syntax for "http://localhost:port" is ":port", e.g. ":8080".
+ name: a full name of service, method or type. If not specified prints names
+ of all available services.
+
+Flags:`,
+ ShortDesc: "lists services and prints a definition of a referenced object.",
+ LongDesc: "Lists services and prints a definition of a referenced object.",
+ CommandRun: func() subcommands.CommandRun {
+ c := &showRun{}
+ c.registerBaseFlags()
+ return c
+ },
+}
+
+type showRun struct {
+ cmdRun
+}
+
+func (r *showRun) Run(a subcommands.Application, args []string) int {
+ if len(args) == 0 || len(args) > 2 {
+ return r.argErr("")
+ }
+
+ server, err := parseServer(args[0])
+ if err != nil {
+ return r.argErr("server: %s", err)
+ }
+ var name string
+ if len(args) > 1 {
+ name = args[1]
+ }
+
+ return r.done(show(r.initContext(), server, name))
+}
+
+// show prints a definition of an object referenced by name in proto3 style.
+func show(c context.Context, server *url.URL, name string) error {
+ desc, err := loadDescription(c, server)
+ if err != nil {
+ return fmt.Errorf("could not load server description: %s", err)
+ }
+
+ if name == "" {
+ for _, s := range desc.services {
+ fmt.Println(s)
+ }
+ return nil
+ }
+
+ file, obj, path := desc.descriptor.Resolve(name)
+ if obj == nil {
+ return fmt.Errorf("name %q could not resolved against %s", name, server)
+ }
+
+ print := newPrinter(os.Stdout)
+ print.File = file
+
+ switch obj := obj.(type) {
+
+ case *descriptor.ServiceDescriptorProto:
+ print.Service(obj, path[1], -1)
+
+ case *descriptor.MethodDescriptorProto:
+ serviceIndex, methodIndex := path[1], path[3]
+ print.Service(file.Service[serviceIndex], serviceIndex, methodIndex)
+
+ printMsg := func(name string) {
+ name = strings.TrimPrefix(name, ".")
+ file, msg, path := desc.descriptor.Resolve(name)
+ if msg == nil {
+ print.Printf("// Message %q is not found\n", name)
+ return
+ }
+ print.File = file
+ print.Message(msg.(*descriptor.DescriptorProto), path)
+ }
+
+ print.Printf("\n")
+ printMsg(obj.GetInputType())
+ print.Printf("\n")
+ printMsg(obj.GetOutputType())
+
+ case *descriptor.DescriptorProto:
+ print.Message(obj, path)
+
+ case *descriptor.FieldDescriptorProto:
+ print.Field(obj, path)
+
+ case *descriptor.EnumDescriptorProto:
+ print.Enum(obj, path)
+
+ case *descriptor.EnumValueDescriptorProto:
+ print.EnumValue(obj, path)
+
+ default:
+ return fmt.Errorf("object of type %T is not supported", obj)
+ }
+
+ return print.Err
+}
+
+type serverDescription struct {
+ services []string
+ descriptor *descriptor.FileDescriptorSet
+}
+
+func loadDescription(c context.Context, server *url.URL) (*serverDescription, error) {
+ // TODO(nodir): cache description on the file system.
+ req := &request{
+ server: server,
+ service: "discovery.Discovery",
+ method: "Describe",
+ format: formatBinary,
+ }
+ var buf bytes.Buffer
+ if err := call(c, req, &buf); err != nil {
+ return nil, fmt.Errorf("could not load server description: %s", err)
+ }
+ var res discovery.DescribeResponse
+ if err := proto.Unmarshal(buf.Bytes(), &res); err != nil {
+ return nil, fmt.Errorf("could not unmarshal response: %s", err)
+ }
+ result := &serverDescription{
+ services: res.Services,
+ descriptor: &descriptor.FileDescriptorSet{},
+ }
+ if err := proto.Unmarshal(res.FileDescriptionSet, result.descriptor); err != nil {
+ return nil, fmt.Errorf("could not unmarshal FileDescriptionSet: %s", err)
+ }
+ return result, nil
+}

Powered by Google App Engine
This is Rietveld 408576698