[ARVADOS] updated: 2.1.0-1510-ga4743d853

Git user git at public.arvados.org
Fri Oct 29 22:15:41 UTC 2021


Summary of changes:
 lib/config/export.go                             |  6 --
 lib/config/load.go                               | 83 --------------------
 lib/controller/federation/conn.go                |  6 +-
 lib/controller/handler_test.go                   | 41 ++++++----
 lib/controller/localdb/collection.go             |  4 +-
 lib/controller/localdb/collection_test.go        |  5 +-
 lib/controller/localdb/conn.go                   | 98 +++++++++++++++++++++++-
 lib/controller/localdb/container_request.go      |  4 +-
 lib/controller/localdb/container_request_test.go |  5 +-
 lib/controller/localdb/group.go                  |  4 +-
 lib/controller/localdb/group_test.go             |  5 +-
 lib/controller/rpc/conn.go                       |  4 +-
 lib/service/cmd.go                               |  4 -
 sdk/go/arvados/api.go                            |  2 +-
 sdk/go/arvados/config.go                         |  1 -
 sdk/go/arvadostest/api.go                        |  4 +-
 16 files changed, 138 insertions(+), 138 deletions(-)

       via  a4743d85331729ad068f052c63d21dba431704ee (commit)
      from  0bf2509a1030e1b2ee0a575fdf1ff69467152dce (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit a4743d85331729ad068f052c63d21dba431704ee
Author: Lucas Di Pentima <lucas.dipentima at curii.com>
Date:   Fri Oct 29 19:14:59 2021 -0300

    17944: Moves vocabulary loading & caching to localdb.Conn
    
    Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima at curii.com>

diff --git a/lib/config/export.go b/lib/config/export.go
index fe33c73d3..f2c15b0ee 100644
--- a/lib/config/export.go
+++ b/lib/config/export.go
@@ -14,12 +14,6 @@ import (
 	"git.arvados.org/arvados.git/sdk/go/arvados"
 )
 
-// ExportVocabularyJSON writes a JSON object with the loaded vocabulary
-// to w.
-func ExportVocabularyJSON(w io.Writer, cluster *arvados.Cluster) error {
-	return json.NewEncoder(w).Encode(cluster.API.Vocabulary)
-}
-
 // ExportJSON writes a JSON object with the safe (non-secret) portions
 // of the cluster config to w.
 func ExportJSON(w io.Writer, cluster *arvados.Cluster) error {
diff --git a/lib/config/load.go b/lib/config/load.go
index 684d7bbe6..248960beb 100644
--- a/lib/config/load.go
+++ b/lib/config/load.go
@@ -17,7 +17,6 @@ import (
 	"strings"
 
 	"git.arvados.org/arvados.git/sdk/go/arvados"
-	"github.com/fsnotify/fsnotify"
 	"github.com/ghodss/yaml"
 	"github.com/imdario/mergo"
 	"github.com/sirupsen/logrus"
@@ -28,7 +27,6 @@ var ErrNoClustersDefined = errors.New("config does not define any clusters")
 type Loader struct {
 	Stdin          io.Reader
 	Logger         logrus.FieldLogger
-	LoadVocabulary bool // Load the vocabulary from API.VocabularyPath
 	SkipDeprecated bool // Don't load deprecated config keys
 	SkipLegacy     bool // Don't load legacy config files
 	SkipAPICalls   bool // Don't do checks that call RailsAPI/controller
@@ -271,9 +269,6 @@ func (ldr *Loader) Load() (*arvados.Config, error) {
 			ldr.loadOldKeepBalanceConfig,
 		)
 	}
-	if ldr.LoadVocabulary {
-		loadFuncs = append(loadFuncs, ldr.loadVocabulary)
-	}
 	loadFuncs = append(loadFuncs, ldr.setImplicitStorageClasses)
 	for _, f := range loadFuncs {
 		err = f(&cfg)
@@ -394,84 +389,6 @@ func (ldr *Loader) checkStorageClasses(cc arvados.Cluster) error {
 	return nil
 }
 
-func (ldr *Loader) loadVocabulary(cfg *arvados.Config) error {
-	cc, err := cfg.GetCluster("")
-	if err != nil {
-		return err
-	}
-	if cc.API.VocabularyPath == "" {
-		return nil
-	}
-	ldr.Logger.Info("Loading vocabulary")
-	voc, err := ldr.vocabularyFileLoader(cc.API.VocabularyPath, cc.Collections.ManagedProperties)
-	if err != nil {
-		return err
-	}
-	cc.API.Vocabulary = voc
-
-	go watchVocabulary(ldr.Logger, cc.API.VocabularyPath, func() {
-		ldr.Logger.Info("Reloading vocabulary")
-		voc, err := ldr.vocabularyFileLoader(cc.API.VocabularyPath, cc.Collections.ManagedProperties)
-		if err != nil {
-			ldr.Logger.Error("Error reloading vocabulary: %v", err)
-		}
-		cc.API.Vocabulary = voc
-	})
-
-	return nil
-}
-
-func (ldr *Loader) vocabularyFileLoader(path string, mp arvados.ManagedProperties) (*arvados.Vocabulary, error) {
-	vf, err := os.ReadFile(path)
-	if err != nil {
-		return nil, fmt.Errorf("couldn't read vocabulary file %q: %v", path, err)
-	}
-	// Managed properties' keys loading
-	mk := make([]string, 0, len(mp))
-	for k := range mp {
-		mk = append(mk, k)
-	}
-	voc, err := arvados.NewVocabulary(vf, mk)
-	if err != nil {
-		return nil, fmt.Errorf("while loading vocabulary file %q: %s", path, err)
-	}
-	ldr.Logger.Info("Vocabulary loading succeeded")
-	return voc, nil
-}
-
-func watchVocabulary(logger logrus.FieldLogger, vocPath string, fn func()) {
-	watcher, err := fsnotify.NewWatcher()
-	if err != nil {
-		logger.WithError(err).Error("vocabulary fsnotify setup failed")
-		return
-	}
-	defer watcher.Close()
-
-	err = watcher.Add(vocPath)
-	if err != nil {
-		logger.WithError(err).Error("vocabulary file watcher failed")
-		return
-	}
-
-	for {
-		select {
-		case err, ok := <-watcher.Errors:
-			if !ok {
-				return
-			}
-			logger.WithError(err).Warn("vocabulary file watcher error")
-		case _, ok := <-watcher.Events:
-			if !ok {
-				return
-			}
-			for len(watcher.Events) > 0 {
-				<-watcher.Events
-			}
-			fn()
-		}
-	}
-}
-
 func checkKeyConflict(label string, m map[string]string) error {
 	saw := map[string]bool{}
 	for k := range m {
diff --git a/lib/controller/federation/conn.go b/lib/controller/federation/conn.go
index 495c87aee..972941622 100644
--- a/lib/controller/federation/conn.go
+++ b/lib/controller/federation/conn.go
@@ -192,10 +192,8 @@ func (conn *Conn) ConfigGet(ctx context.Context) (json.RawMessage, error) {
 	return json.RawMessage(buf.Bytes()), err
 }
 
-func (conn *Conn) VocabularyGet(ctx context.Context) (json.RawMessage, error) {
-	var buf bytes.Buffer
-	err := config.ExportVocabularyJSON(&buf, conn.cluster)
-	return json.RawMessage(buf.Bytes()), err
+func (conn *Conn) VocabularyGet(ctx context.Context) (arvados.Vocabulary, error) {
+	return conn.chooseBackend(conn.cluster.ClusterID).VocabularyGet(ctx)
 }
 
 func (conn *Conn) Login(ctx context.Context, options arvados.LoginOptions) (arvados.LoginResponse, error) {
diff --git a/lib/controller/handler_test.go b/lib/controller/handler_test.go
index 063523c55..c99faba73 100644
--- a/lib/controller/handler_test.go
+++ b/lib/controller/handler_test.go
@@ -89,23 +89,30 @@ func (s *HandlerSuite) TestConfigExport(c *check.C) {
 }
 
 func (s *HandlerSuite) TestVocabularyExport(c *check.C) {
-	s.cluster.API.Vocabulary = &arvados.Vocabulary{
-		Tags: map[string]arvados.VocabularyTag{
+	voc := `{
+		"strict_tags": false,
+		"tags": {
 			"IDTAGIMPORTANCE": {
-				Labels: []arvados.VocabularyLabel{{Label: "Importance"}},
-				Values: map[string]arvados.VocabularyTagValue{
+				"strict": false,
+				"labels": [{"label": "Importance"}],
+				"values": {
 					"HIGH": {
-						Labels: []arvados.VocabularyLabel{{Label: "High"}},
+						"labels": [{"label": "High"}]
 					},
 					"LOW": {
-						Labels: []arvados.VocabularyLabel{{Label: "Low"}},
-					},
-				},
-			},
-		},
-	}
-	err := s.cluster.API.Vocabulary.Validate()
-	c.Check(err, check.IsNil)
+						"labels": [{"label": "Low"}]
+					}
+				}
+			}
+		}
+	}`
+	f, err := os.CreateTemp("", "test-vocabulary-*.json")
+	c.Assert(err, check.IsNil)
+	defer os.Remove(f.Name())
+	_, err = f.WriteString(voc)
+	c.Assert(err, check.IsNil)
+	f.Close()
+	s.cluster.API.VocabularyPath = f.Name()
 	for _, method := range []string{"GET", "OPTIONS"} {
 		c.Log(c.TestName()+" ", method)
 		req := httptest.NewRequest(method, "/arvados/v1/vocabulary", nil)
@@ -122,10 +129,12 @@ func (s *HandlerSuite) TestVocabularyExport(c *check.C) {
 			c.Check(resp.Body.String(), check.HasLen, 0)
 			continue
 		}
-		var voc *arvados.Vocabulary
-		err := json.Unmarshal(resp.Body.Bytes(), &voc)
+		var expectedVoc, receivedVoc *arvados.Vocabulary
+		err := json.Unmarshal([]byte(voc), &expectedVoc)
+		c.Check(err, check.IsNil)
+		err = json.Unmarshal(resp.Body.Bytes(), &receivedVoc)
 		c.Check(err, check.IsNil)
-		c.Check(voc, check.DeepEquals, s.cluster.API.Vocabulary)
+		c.Check(receivedVoc, check.DeepEquals, expectedVoc)
 	}
 }
 
diff --git a/lib/controller/localdb/collection.go b/lib/controller/localdb/collection.go
index 6f99e57c4..96c89252e 100644
--- a/lib/controller/localdb/collection.go
+++ b/lib/controller/localdb/collection.go
@@ -51,7 +51,7 @@ func (conn *Conn) CollectionList(ctx context.Context, opts arvados.ListOptions)
 // CollectionCreate defers to railsProxy for everything except blob
 // signatures and vocabulary checking.
 func (conn *Conn) CollectionCreate(ctx context.Context, opts arvados.CreateOptions) (arvados.Collection, error) {
-	err := conn.checkProperties(opts.Attrs["properties"])
+	err := conn.checkProperties(ctx, opts.Attrs["properties"])
 	if err != nil {
 		return arvados.Collection{}, err
 	}
@@ -72,7 +72,7 @@ func (conn *Conn) CollectionCreate(ctx context.Context, opts arvados.CreateOptio
 // CollectionUpdate defers to railsProxy for everything except blob
 // signatures and vocabulary checking.
 func (conn *Conn) CollectionUpdate(ctx context.Context, opts arvados.UpdateOptions) (arvados.Collection, error) {
-	err := conn.checkProperties(opts.Attrs["properties"])
+	err := conn.checkProperties(ctx, opts.Attrs["properties"])
 	if err != nil {
 		return arvados.Collection{}, err
 	}
diff --git a/lib/controller/localdb/collection_test.go b/lib/controller/localdb/collection_test.go
index 09a8dfbe1..ae996d27b 100644
--- a/lib/controller/localdb/collection_test.go
+++ b/lib/controller/localdb/collection_test.go
@@ -68,7 +68,8 @@ func (s *CollectionSuite) setUpVocabulary(c *check.C, testVocabulary string) {
 	voc, err := arvados.NewVocabulary([]byte(testVocabulary), []string{})
 	c.Assert(err, check.IsNil)
 	c.Assert(voc.Validate(), check.IsNil)
-	s.cluster.API.Vocabulary = voc
+	s.cluster.API.VocabularyPath = "foo"
+	s.localdb.vocabularyCache = voc
 }
 
 func (s *CollectionSuite) TestCollectionCreateWithProperties(c *check.C) {
@@ -94,7 +95,6 @@ func (s *CollectionSuite) TestCollectionCreateWithProperties(c *check.C) {
 				"properties": tt.props,
 			}})
 		if tt.success {
-			c.Assert(err, check.IsNil)
 			c.Assert(err, check.IsNil)
 			c.Assert(coll.Properties, check.DeepEquals, tt.props)
 		} else {
@@ -128,7 +128,6 @@ func (s *CollectionSuite) TestCollectionUpdateWithProperties(c *check.C) {
 				"properties": tt.props,
 			}})
 		if tt.success {
-			c.Assert(err, check.IsNil)
 			c.Assert(err, check.IsNil)
 			c.Assert(coll.Properties, check.DeepEquals, tt.props)
 		} else {
diff --git a/lib/controller/localdb/conn.go b/lib/controller/localdb/conn.go
index a26381f74..bec9354b1 100644
--- a/lib/controller/localdb/conn.go
+++ b/lib/controller/localdb/conn.go
@@ -8,18 +8,24 @@ import (
 	"context"
 	"encoding/json"
 	"fmt"
+	"os"
 	"strings"
 
 	"git.arvados.org/arvados.git/lib/controller/railsproxy"
 	"git.arvados.org/arvados.git/lib/controller/rpc"
 	"git.arvados.org/arvados.git/sdk/go/arvados"
+	"git.arvados.org/arvados.git/sdk/go/ctxlog"
+	"github.com/fsnotify/fsnotify"
+	"github.com/sirupsen/logrus"
 )
 
 type railsProxy = rpc.Conn
 
 type Conn struct {
-	cluster     *arvados.Cluster
-	*railsProxy // handles API methods that aren't defined on Conn itself
+	cluster          *arvados.Cluster
+	*railsProxy      // handles API methods that aren't defined on Conn itself
+	vocabularyCache  *arvados.Vocabulary
+	reloadVocabulary bool
 	loginController
 }
 
@@ -34,7 +40,7 @@ func NewConn(cluster *arvados.Cluster) *Conn {
 	return &conn
 }
 
-func (conn *Conn) checkProperties(properties interface{}) error {
+func (conn *Conn) checkProperties(ctx context.Context, properties interface{}) error {
 	if properties == nil {
 		return nil
 	}
@@ -50,7 +56,91 @@ func (conn *Conn) checkProperties(properties interface{}) error {
 	default:
 		return fmt.Errorf("unexpected properties type %T", properties)
 	}
-	return conn.cluster.API.Vocabulary.Check(props)
+	voc, err := conn.VocabularyGet(ctx)
+	if err != nil {
+		return err
+	}
+	return voc.Check(props)
+}
+
+func watchVocabulary(logger logrus.FieldLogger, vocPath string, fn func()) {
+	watcher, err := fsnotify.NewWatcher()
+	if err != nil {
+		logger.WithError(err).Error("vocabulary fsnotify setup failed")
+		return
+	}
+	defer watcher.Close()
+
+	err = watcher.Add(vocPath)
+	if err != nil {
+		logger.WithError(err).Error("vocabulary file watcher failed")
+		return
+	}
+
+	for {
+		select {
+		case err, ok := <-watcher.Errors:
+			if !ok {
+				return
+			}
+			logger.WithError(err).Warn("vocabulary file watcher error")
+		case _, ok := <-watcher.Events:
+			if !ok {
+				return
+			}
+			for len(watcher.Events) > 0 {
+				<-watcher.Events
+			}
+			fn()
+		}
+	}
+}
+
+func (conn *Conn) loadVocabularyFile() error {
+	vf, err := os.ReadFile(conn.cluster.API.VocabularyPath)
+	if err != nil {
+		return fmt.Errorf("couldn't read vocabulary file %q: %v", conn.cluster.API.VocabularyPath, err)
+	}
+	mk := make([]string, 0, len(conn.cluster.Collections.ManagedProperties))
+	for k := range conn.cluster.Collections.ManagedProperties {
+		mk = append(mk, k)
+	}
+	voc, err := arvados.NewVocabulary(vf, mk)
+	if err != nil {
+		return fmt.Errorf("while loading vocabulary file %q: %s", conn.cluster.API.VocabularyPath, err)
+	}
+	conn.vocabularyCache = voc
+	return nil
+}
+
+// VocabularyGet refreshes the vocabulary cache if necessary and returns it.
+func (conn *Conn) VocabularyGet(ctx context.Context) (arvados.Vocabulary, error) {
+	if conn.cluster.API.VocabularyPath == "" {
+		return arvados.Vocabulary{}, nil
+	}
+	logger := ctxlog.FromContext(ctx)
+	if conn.vocabularyCache == nil {
+		// Initial load of vocabulary file.
+		err := conn.loadVocabularyFile()
+		if err != nil {
+			logger.WithError(err).Error("error loading vocabulary file")
+			return arvados.Vocabulary{}, err
+		}
+		go watchVocabulary(logger, conn.cluster.API.VocabularyPath, func() {
+			logger.Info("vocabulary file changed, it'll be reloaded next time it's needed")
+			conn.reloadVocabulary = true
+		})
+	} else if conn.reloadVocabulary {
+		// Requested reload of vocabulary file.
+		conn.reloadVocabulary = false
+		err := conn.loadVocabularyFile()
+		if err != nil {
+			logger.WithError(err).Error("error reloading vocabulary file - ignoring")
+		} else {
+			logger.Info("vocabulary file reloaded successfully")
+		}
+	}
+	return *conn.vocabularyCache, nil
 }
 
 // Logout handles the logout of conn giving to the appropriate loginController
diff --git a/lib/controller/localdb/container_request.go b/lib/controller/localdb/container_request.go
index b1200be83..5b2ce95da 100644
--- a/lib/controller/localdb/container_request.go
+++ b/lib/controller/localdb/container_request.go
@@ -13,7 +13,7 @@ import (
 // ContainerRequestCreate defers to railsProxy for everything except
 // vocabulary checking.
 func (conn *Conn) ContainerRequestCreate(ctx context.Context, opts arvados.CreateOptions) (arvados.ContainerRequest, error) {
-	err := conn.checkProperties(opts.Attrs["properties"])
+	err := conn.checkProperties(ctx, opts.Attrs["properties"])
 	if err != nil {
 		return arvados.ContainerRequest{}, err
 	}
@@ -27,7 +27,7 @@ func (conn *Conn) ContainerRequestCreate(ctx context.Context, opts arvados.Creat
 // ContainerRequestUpdate defers to railsProxy for everything except
 // vocabulary checking.
 func (conn *Conn) ContainerRequestUpdate(ctx context.Context, opts arvados.UpdateOptions) (arvados.ContainerRequest, error) {
-	err := conn.checkProperties(opts.Attrs["properties"])
+	err := conn.checkProperties(ctx, opts.Attrs["properties"])
 	if err != nil {
 		return arvados.ContainerRequest{}, err
 	}
diff --git a/lib/controller/localdb/container_request_test.go b/lib/controller/localdb/container_request_test.go
index ab9d5b093..c231e3ca7 100644
--- a/lib/controller/localdb/container_request_test.go
+++ b/lib/controller/localdb/container_request_test.go
@@ -65,7 +65,8 @@ func (s *ContainerRequestSuite) setUpVocabulary(c *check.C, testVocabulary strin
 	voc, err := arvados.NewVocabulary([]byte(testVocabulary), []string{})
 	c.Assert(err, check.IsNil)
 	c.Assert(voc.Validate(), check.IsNil)
-	s.cluster.API.Vocabulary = voc
+	s.localdb.vocabularyCache = voc
+	s.cluster.API.VocabularyPath = "foo"
 }
 
 func (s *ContainerRequestSuite) TestCRCreateWithProperties(c *check.C) {
@@ -106,7 +107,6 @@ func (s *ContainerRequestSuite) TestCRCreateWithProperties(c *check.C) {
 				"properties": tt.props,
 			}})
 		if tt.success {
-			c.Assert(err, check.IsNil)
 			c.Assert(err, check.IsNil)
 			c.Assert(cnt.Properties, check.DeepEquals, tt.props)
 		} else {
@@ -158,7 +158,6 @@ func (s *ContainerRequestSuite) TestCRUpdateWithProperties(c *check.C) {
 				"properties": tt.props,
 			}})
 		if tt.success {
-			c.Assert(err, check.IsNil)
 			c.Assert(err, check.IsNil)
 			c.Assert(cnt.Properties, check.DeepEquals, tt.props)
 		} else {
diff --git a/lib/controller/localdb/group.go b/lib/controller/localdb/group.go
index d9617d8bc..0d77bdbd9 100644
--- a/lib/controller/localdb/group.go
+++ b/lib/controller/localdb/group.go
@@ -13,7 +13,7 @@ import (
 // GroupCreate defers to railsProxy for everything except vocabulary
 // checking.
 func (conn *Conn) GroupCreate(ctx context.Context, opts arvados.CreateOptions) (arvados.Group, error) {
-	err := conn.checkProperties(opts.Attrs["properties"])
+	err := conn.checkProperties(ctx, opts.Attrs["properties"])
 	if err != nil {
 		return arvados.Group{}, err
 	}
@@ -27,7 +27,7 @@ func (conn *Conn) GroupCreate(ctx context.Context, opts arvados.CreateOptions) (
 // GroupUpdate defers to railsProxy for everything except vocabulary
 // checking.
 func (conn *Conn) GroupUpdate(ctx context.Context, opts arvados.UpdateOptions) (arvados.Group, error) {
-	err := conn.checkProperties(opts.Attrs["properties"])
+	err := conn.checkProperties(ctx, opts.Attrs["properties"])
 	if err != nil {
 		return arvados.Group{}, err
 	}
diff --git a/lib/controller/localdb/group_test.go b/lib/controller/localdb/group_test.go
index 37bddfbd0..0991f3b72 100644
--- a/lib/controller/localdb/group_test.go
+++ b/lib/controller/localdb/group_test.go
@@ -65,7 +65,8 @@ func (s *GroupSuite) setUpVocabulary(c *check.C, testVocabulary string) {
 	voc, err := arvados.NewVocabulary([]byte(testVocabulary), []string{})
 	c.Assert(err, check.IsNil)
 	c.Assert(voc.Validate(), check.IsNil)
-	s.cluster.API.Vocabulary = voc
+	s.localdb.vocabularyCache = voc
+	s.cluster.API.VocabularyPath = "foo"
 }
 
 func (s *GroupSuite) TestGroupCreateWithProperties(c *check.C) {
@@ -92,7 +93,6 @@ func (s *GroupSuite) TestGroupCreateWithProperties(c *check.C) {
 				"properties":  tt.props,
 			}})
 		if tt.success {
-			c.Assert(err, check.IsNil)
 			c.Assert(err, check.IsNil)
 			c.Assert(grp.Properties, check.DeepEquals, tt.props)
 		} else {
@@ -130,7 +130,6 @@ func (s *GroupSuite) TestGroupUpdateWithProperties(c *check.C) {
 				"properties": tt.props,
 			}})
 		if tt.success {
-			c.Assert(err, check.IsNil)
 			c.Assert(err, check.IsNil)
 			c.Assert(grp.Properties, check.DeepEquals, tt.props)
 		} else {
diff --git a/lib/controller/rpc/conn.go b/lib/controller/rpc/conn.go
index bd9332b03..1acddfab7 100644
--- a/lib/controller/rpc/conn.go
+++ b/lib/controller/rpc/conn.go
@@ -178,9 +178,9 @@ func (conn *Conn) ConfigGet(ctx context.Context) (json.RawMessage, error) {
 	return resp, err
 }
 
-func (conn *Conn) VocabularyGet(ctx context.Context) (json.RawMessage, error) {
+func (conn *Conn) VocabularyGet(ctx context.Context) (arvados.Vocabulary, error) {
 	ep := arvados.EndpointVocabularyGet
-	var resp json.RawMessage
+	var resp arvados.Vocabulary
 	err := conn.requestAndDecode(ctx, &resp, ep, nil, nil)
 	return resp, err
 }
diff --git a/lib/service/cmd.go b/lib/service/cmd.go
index 71c4399f7..e67c24f65 100644
--- a/lib/service/cmd.go
+++ b/lib/service/cmd.go
@@ -94,10 +94,6 @@ func (c *command) RunCommand(prog string, args []string, stdin io.Reader, stdout
 		// process _is_ the controller: we haven't started an
 		// http server yet.
 		loader.SkipAPICalls = true
-		// The vocabulary file is expected to be present only
-		// in the controller node, so it doesn't make sense to
-		// try loading it elsewhere.
-		loader.LoadVocabulary = true
 	}
 
 	cfg, err := loader.Load()
diff --git a/sdk/go/arvados/api.go b/sdk/go/arvados/api.go
index 63f784f15..41727beea 100644
--- a/sdk/go/arvados/api.go
+++ b/sdk/go/arvados/api.go
@@ -220,7 +220,7 @@ type BlockWriteResponse struct {
 
 type API interface {
 	ConfigGet(ctx context.Context) (json.RawMessage, error)
-	VocabularyGet(ctx context.Context) (json.RawMessage, error)
+	VocabularyGet(ctx context.Context) (Vocabulary, error)
 	Login(ctx context.Context, options LoginOptions) (LoginResponse, error)
 	Logout(ctx context.Context, options LogoutOptions) (LogoutResponse, error)
 	CollectionCreate(ctx context.Context, options CreateOptions) (Collection, error)
diff --git a/sdk/go/arvados/config.go b/sdk/go/arvados/config.go
index 87b71bfbe..1cd002082 100644
--- a/sdk/go/arvados/config.go
+++ b/sdk/go/arvados/config.go
@@ -108,7 +108,6 @@ type Cluster struct {
 		WebsocketClientEventQueue      int
 		WebsocketServerEventQueue      int
 		KeepServiceRequestTimeout      Duration
-		Vocabulary                     *Vocabulary `json:"-"`
 		VocabularyPath                 string
 	}
 	AuditLogs struct {
diff --git a/sdk/go/arvadostest/api.go b/sdk/go/arvadostest/api.go
index 64f7235f3..2cb35366c 100644
--- a/sdk/go/arvadostest/api.go
+++ b/sdk/go/arvadostest/api.go
@@ -33,9 +33,9 @@ func (as *APIStub) ConfigGet(ctx context.Context) (json.RawMessage, error) {
 	as.appendCall(ctx, as.ConfigGet, nil)
 	return nil, as.Error
 }
-func (as *APIStub) VocabularyGet(ctx context.Context) (json.RawMessage, error) {
+func (as *APIStub) VocabularyGet(ctx context.Context) (arvados.Vocabulary, error) {
 	as.appendCall(ctx, as.VocabularyGet, nil)
-	return nil, as.Error
+	return arvados.Vocabulary{}, as.Error
 }
 func (as *APIStub) Login(ctx context.Context, options arvados.LoginOptions) (arvados.LoginResponse, error) {
 	as.appendCall(ctx, as.Login, options)

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list