| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2016 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. |
| 4 |
| 5 package gaeconfig |
| 6 |
| 7 import ( |
| 8 "errors" |
| 9 "fmt" |
| 10 "os" |
| 11 "path/filepath" |
| 12 "time" |
| 13 |
| 14 "github.com/luci/luci-go/common/config/impl/filesystem" |
| 15 "github.com/luci/luci-go/luci_config/appengine/backend/memcache" |
| 16 gaeformat "github.com/luci/luci-go/luci_config/appengine/format" |
| 17 "github.com/luci/luci-go/luci_config/server/cfgclient/backend" |
| 18 "github.com/luci/luci-go/luci_config/server/cfgclient/backend/caching" |
| 19 "github.com/luci/luci-go/luci_config/server/cfgclient/backend/client" |
| 20 "github.com/luci/luci-go/luci_config/server/cfgclient/backend/erroring" |
| 21 "github.com/luci/luci-go/luci_config/server/cfgclient/backend/format" |
| 22 "github.com/luci/luci-go/luci_config/server/cfgclient/backend/testconfig
" |
| 23 |
| 24 "github.com/luci/gae/service/info" |
| 25 |
| 26 "golang.org/x/net/context" |
| 27 ) |
| 28 |
| 29 // ErrNotConfigured is returned by cfgclient methods if the config service URL |
| 30 // is not set. Usually happens for new apps. |
| 31 var ErrNotConfigured = errors.New("config service URL is not set in settings") |
| 32 |
| 33 // devCfgDir is a name of the directory with config files when running in |
| 34 // local dev appserver model. See New for details. |
| 35 const devCfgDir = "devcfg" |
| 36 |
| 37 // Use installs the default luci-config client. |
| 38 // |
| 39 // The client is configured to use luci-config URL specified in the settings, |
| 40 // using GAE app service account for authentication. |
| 41 // |
| 42 // If running in prod, and the settings don't specify luci-config URL, produces |
| 43 // an implementation of backend.B that returns ErrNotConfigured from all |
| 44 // methods. |
| 45 // |
| 46 // If running on devserver, and the settings don't specify luci-config URL, |
| 47 // returns a filesystem-based implementation that reads configs from a directory |
| 48 // (or a symlink) named 'devcfg' located in the GAE module directory (where |
| 49 // app.yaml is) or its immediate parent directory. |
| 50 // |
| 51 // If such directory can not be located, produces an implementation of |
| 52 // cfgclient that returns errors from all methods. |
| 53 // |
| 54 // Panics if it can't load the settings (should not happen since they are in |
| 55 // the local memory cache usually). |
| 56 func Use(c context.Context) context.Context { return useImpl(c, nil) } |
| 57 |
| 58 func useImpl(c context.Context, be backend.B) context.Context { |
| 59 return installConfigBackend(c, mustFetchCachedSettings(c), be) |
| 60 } |
| 61 |
| 62 func installConfigBackend(c context.Context, s *Settings, be backend.B) context.
Context { |
| 63 if be == nil { |
| 64 // Non-testing, build a Backend. |
| 65 be = getPrimaryBackend(c, s) |
| 66 } |
| 67 |
| 68 // Install a FormatRegistry. Register common config service protobufs wi
th it. |
| 69 c = gaeformat.WithRegistry(c, gaeformat.Default()) |
| 70 |
| 71 be = &format.Backend{ |
| 72 B: be, |
| 73 GetRegistry: gaeformat.GetRegistry, |
| 74 } |
| 75 |
| 76 // Apply caching configuration. |
| 77 exp := time.Duration(s.CacheExpirationSec) * time.Second |
| 78 if exp > 0 { |
| 79 // Add a ProcCache, backed by memcache. |
| 80 be = memcache.Backend(be, exp) |
| 81 be = caching.ProcCache(be, exp) |
| 82 } |
| 83 |
| 84 c = backend.WithBackend(c, be) |
| 85 return c |
| 86 } |
| 87 |
| 88 func getPrimaryBackend(c context.Context, settings *Settings) backend.B { |
| 89 // Identify our config service backend (in testing, it will be supplied)
. |
| 90 if settings.ConfigServiceURL == "" { |
| 91 if info.IsDevAppServer(c) { |
| 92 return devServerBackend() |
| 93 } |
| 94 return erroring.New(ErrNotConfigured) |
| 95 } |
| 96 return &client.Backend{&client.RemoteProvider{ |
| 97 BaseURL: settings.ConfigServiceURL, |
| 98 }} |
| 99 } |
| 100 |
| 101 // devServerConfig returns backend.B to use on a devserver. |
| 102 // |
| 103 // See New for details. |
| 104 func devServerBackend() backend.B { |
| 105 pwd := os.Getenv("PWD") // os.Getwd works funny with symlinks, use PWD |
| 106 candidates := []string{ |
| 107 filepath.Join(pwd, devCfgDir), |
| 108 filepath.Join(filepath.Dir(pwd), devCfgDir), |
| 109 } |
| 110 for _, dir := range candidates { |
| 111 if _, err := os.Stat(dir); err == nil { |
| 112 fs, err := filesystem.New(dir) |
| 113 if err != nil { |
| 114 return erroring.New(err) |
| 115 } |
| 116 return &client.Backend{&testconfig.Provider{ |
| 117 Base: fs, |
| 118 }} |
| 119 } |
| 120 } |
| 121 return erroring.New(fmt.Errorf("luci-config: could not find local config
s in any of %s", candidates)) |
| 122 } |
| OLD | NEW |