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

Side by Side Diff: logdog/appengine/coordinator/config/projects.go

Issue 2575383002: Add server/cache support to gaeconfig. (Closed)
Patch Set: 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 unified diff | Download patch
OLDNEW
1 // Copyright 2015 The LUCI Authors. All rights reserved. 1 // Copyright 2015 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0 2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file. 3 // that can be found in the LICENSE file.
4 4
5 package config 5 package config
6 6
7 import ( 7 import (
8 "fmt" 8 "fmt"
9 » "strings" 9 » "sort"
10 10
11 "github.com/golang/protobuf/proto"
12 "github.com/luci/gae/service/info" 11 "github.com/luci/gae/service/info"
13 » "github.com/luci/luci-go/common/config" 12 » ccfg "github.com/luci/luci-go/common/config"
14 log "github.com/luci/luci-go/common/logging" 13 log "github.com/luci/luci-go/common/logging"
15 "github.com/luci/luci-go/logdog/api/config/svcconfig" 14 "github.com/luci/luci-go/logdog/api/config/svcconfig"
15 "github.com/luci/luci-go/server/config"
16 "github.com/luci/luci-go/server/config/textproto"
17
16 "golang.org/x/net/context" 18 "golang.org/x/net/context"
17 ) 19 )
18 20
19 const maxProjectWorkers = 32
20
21 // ProjectConfigPath returns the path of the project-specific configuration. 21 // ProjectConfigPath returns the path of the project-specific configuration.
22 // This path should be used with a project config set. 22 // This path should be used with a project config set.
23 // 23 //
24 // A given project's configuration is named after the current App ID. 24 // A given project's configuration is named after the current App ID.
25 func ProjectConfigPath(c context.Context) string { 25 func ProjectConfigPath(c context.Context) string {
26 return fmt.Sprintf("%s.cfg", info.AppID(c)) 26 return fmt.Sprintf("%s.cfg", info.AppID(c))
27 } 27 }
28 28
29 // ProjectConfig loads the project config protobuf from the config service. 29 // ProjectConfig loads the project config protobuf from the config service.
30 // 30 //
31 // This function will return: 31 // This function will return:
32 // - nil, if the project exists and the configuration successfully loaded 32 // - nil, if the project exists and the configuration successfully loaded
33 // - config.ErrNoConfig if the project configuration was not present. 33 // - config.ErrNoConfig if the project configuration was not present.
34 // - ErrInvalidConfig if the project configuration was present, but could n ot 34 // - ErrInvalidConfig if the project configuration was present, but could n ot
35 // be loaded. 35 // be loaded.
36 // - Some other error if an error occurred that does not fit one of the 36 // - Some other error if an error occurred that does not fit one of the
37 // previous categories. 37 // previous categories.
38 func ProjectConfig(c context.Context, project config.ProjectName) (*svcconfig.Pr ojectConfig, error) { 38 func ProjectConfig(c context.Context, project ccfg.ProjectName) (*svcconfig.Proj ectConfig, error) {
39 if project == "" { 39 if project == "" {
40 return nil, config.ErrNoConfig 40 return nil, config.ErrNoConfig
41 } 41 }
42 42
43 // Get the config from the config service. If the configuration doesn't exist, 43 // Get the config from the config service. If the configuration doesn't exist,
44 // this will return config.ErrNoConfig. 44 // this will return config.ErrNoConfig.
45 configSet, configPath := config.ProjectConfigSet(project), ProjectConfig Path(c) 45 configSet, configPath := config.ProjectConfigSet(project), ProjectConfig Path(c)
46 » cfg, err := config.GetConfig(c, configSet, configPath, false) 46
47 » if err != nil { 47 » var pcfg svcconfig.ProjectConfig
48 » if err := config.Get(c, config.AsService, configSet, configPath, textpro to.Message(&pcfg), nil); err != nil {
48 log.Fields{ 49 log.Fields{
49 log.ErrorKey: err, 50 log.ErrorKey: err,
50 "project": project, 51 "project": project,
51 "configSet": configSet, 52 "configSet": configSet,
52 "configPath": configPath, 53 "configPath": configPath,
53 }.Errorf(c, "Failed to load project configuration content.") 54 }.Errorf(c, "Failed to load project configuration content.")
54 return nil, err 55 return nil, err
55 } 56 }
56 57 » return &pcfg, nil
57 » pcfg, err := unmarshalProjectConfig(cfg)
58 » if err != nil {
59 » » log.Fields{
60 » » » log.ErrorKey: err,
61 » » » "project": project,
62 » » » "configSet": cfg.ConfigSet,
63 » » » "path": cfg.Path,
64 » » » "contentHash": cfg.ContentHash,
65 » » }.Errorf(c, "Failed to unmarshal project configuration.")
66 » » return nil, ErrInvalidConfig
67 » }
68 » return pcfg, nil
69 } 58 }
70 59
71 // AllProjectConfigs returns the project configurations for all projects that 60 // ProjectNames returns a sorted list of the names of all of the projects
72 // have a configuration. 61 // that the supplied authority can view.
73 // 62 func ProjectNames(c context.Context, a config.Authority) ([]ccfg.ProjectName, er ror) {
74 // If a project's configuration fails to load, an error will be logged and the 63 » configPath := ProjectConfigPath(c)
75 // project will be omitted from the output map. 64
76 func AllProjectConfigs(c context.Context) (map[config.ProjectName]*svcconfig.Pro jectConfig, error) { 65 » var metas []*config.Meta
77 » // TODO: This endpoint is generally slow. Even though there is memcache- based 66 » if err := config.GetAll(c, a, config.Project, configPath, nil, &metas); err != nil {
78 » // config cache, this really should be loaded from a more failsafe cache like
79 » // datastore to protect against config service outages.
80 » configs, err := config.GetProjectConfigs(c, ProjectConfigPath(c), false)
81 » if err != nil {
82 log.WithError(err).Errorf(c, "Failed to load project configs.") 67 log.WithError(err).Errorf(c, "Failed to load project configs.")
83 return nil, err 68 return nil, err
84 } 69 }
85 70
86 » result := make(map[config.ProjectName]*svcconfig.ProjectConfig, len(conf igs)) 71 » // Iterate through our Metas and extract the project names.
87 » for _, cfg := range configs { 72 » projects := make([]ccfg.ProjectName, 0, len(metas))
88 » » // Identify the project by removng the "projects/" prefix. 73 » for _, meta := range metas {
89 » » project := config.ProjectName(strings.TrimPrefix(cfg.ConfigSet, "projects/")) 74 » » projectName, _, _ := config.ParseProjectConfigSet(meta.ConfigSet )
90 » » if err := project.Validate(); err != nil { 75 » » if projectName != "" {
91 » » » log.Fields{ 76 » » » projects = append(projects, projectName)
92 » » » » log.ErrorKey: err,
93 » » » » "configSet": cfg.ConfigSet,
94 » » » }.Errorf(c, "Invalid project name returned.")
95 » » » continue
96 } 77 }
97
98 // Unmarshal the project's configuration.
99 pcfg, err := unmarshalProjectConfig(&cfg)
100 if err != nil {
101 log.Fields{
102 log.ErrorKey: err,
103 "configSet": cfg.ConfigSet,
104 "path": cfg.Path,
105 "contentHash": cfg.ContentHash,
106 }.Errorf(c, "Failed to unmarshal project configuration." )
107 continue
108 }
109
110 result[project] = pcfg
111 } 78 }
112 » return result, nil 79 » sort.Sort(projectNameSlice(projects))
80 » return projects, nil
113 } 81 }
114 82
115 func unmarshalProjectConfig(cfg *config.Config) (*svcconfig.ProjectConfig, error ) { 83 // ActiveProjects returns a full list of all config service projects with
116 » var pcfg svcconfig.ProjectConfig 84 // LogDog project configurations.
117 » if err := proto.UnmarshalText(cfg.Content, &pcfg); err != nil { 85 //
118 » » return nil, err 86 // The list will be alphabetically sorted.
119 » } 87 func ActiveProjects(c context.Context) ([]ccfg.ProjectName, error) {
120 » return &pcfg, nil 88 » return ProjectNames(c, config.AsService)
121 } 89 }
90
91 // ActiveUserProjects returns a full list of all config service projects with
92 // LogDog project configurations that the current user can see.
93 //
94 // The list will be alphabetically sorted.
95 func ActiveUserProjects(c context.Context) ([]ccfg.ProjectName, error) {
96 return ProjectNames(c, config.AsUser)
97 }
98
99 type projectNameSlice []ccfg.ProjectName
100
101 func (s projectNameSlice) Len() int { return len(s) }
102 func (s projectNameSlice) Less(i, j int) bool { return s[i] < s[j] }
103 func (s projectNameSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698