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

Unified Diff: server/config/config.go

Issue 2580713002: Implement a server-side config service interface. (Closed)
Patch Set: Update MultiResolver interface, add test for MultiError. Created 4 years 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: server/config/config.go
diff --git a/server/config/config.go b/server/config/config.go
new file mode 100644
index 0000000000000000000000000000000000000000..66e66fc4b7656883597387c31c7dfb0ac14ac4cb
--- /dev/null
+++ b/server/config/config.go
@@ -0,0 +1,188 @@
+// Copyright 2016 The LUCI Authors. All rights reserved.
+// Use of this source code is governed under the Apache License, Version 2.0
+// that can be found in the LICENSE file.
+
+package config
+
+import (
+ "encoding/json"
+ "net/url"
+
+ "github.com/luci/luci-go/common/config"
+ "github.com/luci/luci-go/common/errors"
+
+ "golang.org/x/net/context"
+)
+
+// ErrNoConfig is a sentinel error returned by Get when the requested
+// configuration is not found.
iannucci 2017/01/07 20:12:16 I would mention that it's an alias of config.ErrNo
dnj 2017/01/10 03:25:57 Done.
+var ErrNoConfig = config.ErrNoConfig
+
+// GetAllType is the type of configuration to retrieve with GetAll.
+//
+// GetAllType marshals/unmarshals to/from a compact JSON representation. This is
+// used by the caching layer.
+type GetAllType string
+
+const (
+ // Project indicates that project configus should be retrieved.
+ Project = GetAllType("Project")
+ // Ref indicates that ref configs should be retrieved.
+ Ref = GetAllType("Ref")
+)
+
+// MarshalJSON implements json.Marshaler.
+func (gat GetAllType) MarshalJSON() ([]byte, error) {
+ switch gat {
+ case Project:
+ return json.Marshal("P")
+ case Ref:
+ return json.Marshal("R")
+ default:
+ return nil, errors.Reason("unknown GetAllType: %(value)v").D("value", gat).Err()
+ }
+}
+
+// UnmarshalJSON implements json.Unmarshaler.
+func (gat *GetAllType) UnmarshalJSON(d []byte) error {
iannucci 2017/01/07 20:12:15 same as other *JSON methods re: constant []byte va
dnj 2017/01/10 03:25:57 Done.
+ var v string
+ if err := json.Unmarshal(d, &v); err != nil {
+ return errors.Annotate(err).Err()
+ }
+
+ switch v {
+ case "P":
+ *gat = Project
+ return nil
+ case "R":
+ *gat = Ref
+ return nil
+ default:
+ return errors.Reason("unknown GetAllType: %(value)q").D("value", v).Err()
+ }
+}
+
+// Meta is metadata about a configuration.
+type Meta struct {
+ // ConfigSet is the item's config set.
+ ConfigSet string
+ // Path is the item's path within its config set.
+ Path string
+
+ // ContentHash is the content hash.
+ ContentHash string
+ // Revision is the revision string.
+ Revision string
+}
+
+// ServiceURL returns the URL of the config service.
+func ServiceURL(c context.Context) url.URL { return getBackend(c).ServiceURL(c) }
+
+// Get retrieves a single configuration.
iannucci 2017/01/07 20:12:16 can we call them 'configuration file's? Since from
dnj 2017/01/10 03:25:57 Done.
+//
+// r, if supplied, is a MultiResolver that will load the configuration data.
+// If nil, the configuration data will be discarded (useful if you only care
+// about metas).
+//
+// meta, if not nil, will have the configuration's Meta loaded into it on
+// success.
+func Get(c context.Context, a Authority, configSet, path string, r Resolver, meta *Meta) error {
+ be := getBackend(c)
+
+ params := Params{
+ Authority: a,
+ Content: true,
+ }
+
+ if fr, ok := r.(FormattingResolver); ok {
+ params.Format, params.FormatData = fr.Format()
+ }
+
+ item, err := be.Get(c, configSet, path, params)
iannucci 2017/01/07 20:12:15 maybe the Params thing would be clearer if backend
dnj 2017/01/10 03:25:58 Yeah I was debating doing this. I think I was out
+ if err != nil {
+ return err
+ }
+
+ if meta != nil {
+ *meta = item.Meta
+ }
+ if r == nil {
+ return nil
+ }
+ return r.Resolve(item)
+}
+
+// GetAll retrieves all configurations of a given type.
+//
+// r, if supplied, is a MultiResolver that will load the configuration data.
+// If nil, the configuration data will be discarded (useful if you only care
+// about metas). If the MultiResolver operates on a slice (which it probably
+// will), each meta and/or error index will correspond to its slice index.
+//
+// If meta is not nil, it will be populated with a slice of *Meta entries
+// for each loaded configuration, in the same order that r receives them. If
+// r resolves to a slice, the indexes for each resolved slice entry and meta
+// entry should align unless r is doing something funky.
+//
+// Two types of failure may happen here. A systemic failure fails to load the
+// set of project configurations. This will be returned directly.
+//
+// A resolver failure happens when the configuratiokns load, but could not be
+// resolved. In this case, any successful resolutions and "meta" will be
+// populated and an errors.MultiError will be returned containing non-nil
+// errors at indices whose configs failed to resolve.
+func GetAll(c context.Context, a Authority, t GetAllType, path string, r MultiResolver, meta *[]*Meta) error {
+ be := getBackend(c)
+
+ params := Params{
+ Authority: a,
+ Content: true,
+ }
+
+ if fr, ok := r.(FormattingResolver); ok {
+ params.Format, params.FormatData = fr.Format()
+ }
+
+ items, err := be.GetAll(c, t, path, params)
+ if err != nil {
+ return err
+ }
+
+ // Load our metas.
+ if meta != nil {
+ metaSlice := *meta
+ if metaSlice == nil {
+ metaSlice = make([]*Meta, 0, len(items))
+ } else {
+ // Re-use the supplied slice.
+ metaSlice = metaSlice[:0]
+ }
+
+ for _, item := range items {
+ metaSlice = append(metaSlice, &item.Meta)
+ }
+
+ *meta = metaSlice
+ }
+
+ if r == nil {
+ return nil
+ }
+
+ // Resolve our items. If any individual resolution fails, return that failure
+ // as a positional error in a MultiError.
+ lme := errors.NewLazyMultiError(len(items))
+ r.PrepareMulti(len(items))
+ for i, it := range items {
+ if err := r.ResolveItemAt(i, it); err != nil {
+ lme.Assign(i, err)
+ }
+ }
+ return lme.Get()
+}
+
+// GetConfigSetURL returns the URL where the specified ConfigSet is
+// configured. If the config set doesn't exist, ErrNoConfig will be returned.
+func GetConfigSetURL(c context.Context, a Authority, configSet string) (url.URL, error) {
+ return getBackend(c).ConfigSetURL(c, a, configSet)
+}

Powered by Google App Engine
This is Rietveld 408576698