12876: arvados-client get [-format=yaml] uuid
authorTom Clegg <tclegg@veritasgenetics.com>
Fri, 22 Dec 2017 14:45:58 +0000 (09:45 -0500)
committerTom Clegg <tclegg@veritasgenetics.com>
Tue, 2 Jan 2018 14:44:22 +0000 (09:44 -0500)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tclegg@veritasgenetics.com>

build/run-build-packages-one-target.sh
build/run-build-packages.sh
build/run-tests.sh
cmd/arvados-client/.gitignore [new file with mode: 0644]
cmd/arvados-client/cmd.go [new file with mode: 0644]
cmd/arvados-client/cmd_test.go [new file with mode: 0644]
lib/cli/get.go [new file with mode: 0644]
lib/cmd/cmd.go [new file with mode: 0644]
sdk/go/arvadostest/fixtures.go

index ff82e46e049b2014889ffc237a53258fd03e70ae..2af01e3134d4797d6c601ad603e8449e90fd045d 100755 (executable)
@@ -161,6 +161,7 @@ popd
 
 if test -z "$packages" ; then
     packages="arvados-api-server
+        arvados-client
         arvados-git-httpd
         arvados-node-manager
         arvados-src
index 54f8b0aed17e0f49d49d3ea26a6f3d0e2238355a..c56b74088f070c3c252b7c9f84e92eb5e3fea78c 100755 (executable)
@@ -341,6 +341,8 @@ fi
 cd $WORKSPACE/packages/$TARGET
 export GOPATH=$(mktemp -d)
 go get github.com/kardianos/govendor
+package_go_binary cmd/arvados-client arvados-client \
+    "Arvados command line tool (beta)"
 package_go_binary sdk/go/crunchrunner crunchrunner \
     "Crunchrunner executes a command inside a container and uploads the output"
 package_go_binary services/arv-git-httpd arvados-git-httpd \
index 7d6cb9ec8b81dc20dc9094cd33a564805a8a6f16..5114cef3f3a7bbcfa35e5e5304495603440549b6 100755 (executable)
@@ -69,7 +69,10 @@ apps/workbench_functionals (*)
 apps/workbench_integration (*)
 apps/workbench_benchmark
 apps/workbench_profile
+cmd/arvados-client
 doc
+lib/cli
+lib/crunchstat
 services/api
 services/arv-git-httpd
 services/crunchstat
@@ -829,6 +832,9 @@ cd "$GOPATH/src/git.curoverse.com/arvados.git" && \
         fatal "govendor sync failed"
 declare -a gostuff
 gostuff=(
+    cmd/arvados-client
+    lib/cli
+    lib/crunchstat
     sdk/go/arvados
     sdk/go/arvadosclient
     sdk/go/blockdigest
@@ -839,7 +845,6 @@ gostuff=(
     sdk/go/asyncbuf
     sdk/go/crunchrunner
     sdk/go/stats
-    lib/crunchstat
     services/arv-git-httpd
     services/crunchstat
     services/health
diff --git a/cmd/arvados-client/.gitignore b/cmd/arvados-client/.gitignore
new file mode 100644 (file)
index 0000000..21dd863
--- /dev/null
@@ -0,0 +1 @@
+arvados-*
diff --git a/cmd/arvados-client/cmd.go b/cmd/arvados-client/cmd.go
new file mode 100644 (file)
index 0000000..0df1b0c
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: Apache-2.0
+
+package main
+
+import (
+       "fmt"
+       "io"
+       "os"
+       "regexp"
+       "runtime"
+
+       "git.curoverse.com/arvados.git/lib/cli"
+       "git.curoverse.com/arvados.git/lib/cmd"
+)
+
+var version = "dev"
+
+var Run = cmd.Multi(map[string]cmd.RunFunc{
+       "get":       cli.Get,
+       "version":   cmdVersion,
+       "-version":  cmdVersion,
+       "--version": cmdVersion,
+})
+
+func cmdVersion(prog string, args []string, _ io.Reader, stdout, _ io.Writer) int {
+       prog = regexp.MustCompile(` -*version$`).ReplaceAllLiteralString(prog, "")
+       fmt.Fprintf(stdout, "%s %s (%s)\n", prog, version, runtime.Version())
+       return 0
+}
+
+func main() {
+       os.Exit(Run(os.Args[0], os.Args[1:], os.Stdin, os.Stdout, os.Stderr))
+}
diff --git a/cmd/arvados-client/cmd_test.go b/cmd/arvados-client/cmd_test.go
new file mode 100644 (file)
index 0000000..b1ab5ba
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: Apache-2.0
+
+package main
+
+import (
+       "bytes"
+       "io/ioutil"
+       "testing"
+
+       check "gopkg.in/check.v1"
+)
+
+// Gocheck boilerplate
+func Test(t *testing.T) {
+       check.TestingT(t)
+}
+
+var _ = check.Suite(&ClientSuite{})
+
+type ClientSuite struct{}
+
+func (s *ClientSuite) TestBadCommand(c *check.C) {
+       exited := Run("arvados-client", []string{"no such command"}, bytes.NewReader(nil), ioutil.Discard, ioutil.Discard)
+       c.Check(exited, check.Equals, 2)
+}
+
+func (s *ClientSuite) TestBadSubcommandArgs(c *check.C) {
+       exited := Run("arvados-client", []string{"get"}, bytes.NewReader(nil), ioutil.Discard, ioutil.Discard)
+       c.Check(exited, check.Equals, 2)
+}
+
+func (s *ClientSuite) TestVersion(c *check.C) {
+       stdout := bytes.NewBuffer(nil)
+       stderr := bytes.NewBuffer(nil)
+       exited := Run("arvados-client", []string{"version"}, bytes.NewReader(nil), stdout, stderr)
+       c.Check(exited, check.Equals, 0)
+       c.Check(stdout.String(), check.Matches, `arvados-client dev \(go[0-9\.]+\)\n`)
+       c.Check(stderr.String(), check.Equals, "")
+}
diff --git a/lib/cli/get.go b/lib/cli/get.go
new file mode 100644 (file)
index 0000000..725c696
--- /dev/null
@@ -0,0 +1,65 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: Apache-2.0
+
+package cli
+
+import (
+       "encoding/json"
+       "flag"
+       "fmt"
+       "io"
+
+       "git.curoverse.com/arvados.git/sdk/go/arvados"
+       "github.com/ghodss/yaml"
+)
+
+func Get(prog string, args []string, stdin io.Reader, stdout, stderr io.Writer) int {
+       var err error
+       defer func() {
+               if err != nil {
+                       fmt.Fprintf(stderr, "%s\n", err)
+               }
+       }()
+
+       flags := flag.NewFlagSet(prog, flag.ContinueOnError)
+       format := flags.String("format", "json", "output format (json or yaml)")
+       err = flags.Parse(args)
+       if err != nil {
+               return 2
+       }
+       if len(flags.Args()) != 1 {
+               flags.Usage()
+               return 2
+       }
+
+       id := flags.Args()[0]
+       client := arvados.NewClientFromEnv()
+       path, err := client.PathForUUID("show", id)
+       if err != nil {
+               return 1
+       }
+
+       var obj map[string]interface{}
+       err = client.RequestAndDecode(&obj, "GET", path, nil, nil)
+       if err != nil {
+               err = fmt.Errorf("GET %s: %s", path, err)
+               return 1
+       }
+       if *format == "yaml" {
+               var buf []byte
+               buf, err = yaml.Marshal(obj)
+               if err == nil {
+                       _, err = stdout.Write(buf)
+               }
+       } else {
+               enc := json.NewEncoder(stdout)
+               enc.SetIndent("", "  ")
+               err = enc.Encode(obj)
+       }
+       if err != nil {
+               err = fmt.Errorf("encoding: %s", err)
+               return 1
+       }
+       return 0
+}
diff --git a/lib/cmd/cmd.go b/lib/cmd/cmd.go
new file mode 100644 (file)
index 0000000..03b751a
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: Apache-2.0
+
+// package cmd defines a RunFunc type, representing a process that can
+// be invoked from a command line.
+package cmd
+
+import (
+       "fmt"
+       "io"
+)
+
+// A RunFunc runs a command with the given args, and returns an exit
+// code.
+type RunFunc func(prog string, args []string, stdin io.Reader, stdout, stderr io.Writer) int
+
+// Multi returns a command that looks up its first argument in m, and
+// runs the resulting RunFunc with the remaining args.
+//
+// Example:
+//
+//     os.Exit(Multi(map[string]RunFunc{
+//             "foobar": func(prog string, args []string) int {
+//                     fmt.Println(args[0])
+//                     return 2
+//             },
+//     })("/usr/bin/multi", []string{"foobar", "baz"}))
+//
+// ...prints "baz" and exits 2.
+func Multi(m map[string]RunFunc) RunFunc {
+       return func(prog string, args []string, stdin io.Reader, stdout, stderr io.Writer) int {
+               if len(args) < 1 {
+                       fmt.Fprintf(stderr, "usage: %s command [args]", prog)
+                       return 2
+               }
+               if cmd, ok := m[args[0]]; !ok {
+                       fmt.Fprintf(stderr, "unrecognized command %q", args[0])
+                       return 2
+               } else {
+                       return cmd(prog+" "+args[0], args[1:], stdin, stdout, stderr)
+               }
+       }
+}
index 3a611a3bfb14359cca0ab890f47da13314d16a9b..5e530658abe96534d9ed3488a975a85a778af16d 100644 (file)
@@ -16,6 +16,7 @@ const (
        SpectatorUserUUID       = "zzzzz-tpzed-l1s2piq4t4mps8r"
        UserAgreementCollection = "zzzzz-4zz18-uukreo9rbgwsujr" // user_agreement_in_anonymously_accessible_project
        FooCollection           = "zzzzz-4zz18-fy296fx3hot09f7"
+       FooCollectionPDH        = "1f4b0bc7583c2a7f9102c395f4ffc5e3+45"
        NonexistentCollection   = "zzzzz-4zz18-totallynotexist"
        HelloWorldCollection    = "zzzzz-4zz18-4en62shvi99lxd4"
        FooBarDirCollection     = "zzzzz-4zz18-foonbarfilesdir"