OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package coordinator | 5 package coordinator |
6 | 6 |
7 import ( | 7 import ( |
8 "strings" | 8 "strings" |
9 | 9 |
10 "github.com/luci/gae/service/datastore/meta" | |
11 "github.com/luci/gae/service/info" | 10 "github.com/luci/gae/service/info" |
12 » "github.com/luci/luci-go/common/config" | 11 » "github.com/luci/luci-go/appengine/logdog/coordinator/config" |
12 » luciConfig "github.com/luci/luci-go/common/config" | |
13 » log "github.com/luci/luci-go/common/logging" | |
13 "github.com/luci/luci-go/common/proto/logdog/svcconfig" | 14 "github.com/luci/luci-go/common/proto/logdog/svcconfig" |
14 "golang.org/x/net/context" | 15 "golang.org/x/net/context" |
15 ) | 16 ) |
16 | 17 |
17 // projectNamespacePrefix is the datastore namespace prefix for project | 18 const ( |
18 // namespaces. | 19 » // projectNamespacePrefix is the datastore namespace prefix for project |
19 const projectNamespacePrefix = "luci." | 20 » // namespaces. |
21 » projectNamespacePrefix = "luci." | |
22 | |
23 » // projectConfigWorkers is the number of workers that will pull project | |
24 » // configs from the config service. | |
25 » projectConfigWorkers = 16 | |
26 ) | |
20 | 27 |
21 // ProjectNamespace returns the AppEngine namespace for a given luci-config | 28 // ProjectNamespace returns the AppEngine namespace for a given luci-config |
22 // project name. | 29 // project name. |
23 func ProjectNamespace(project config.ProjectName) string { | 30 func ProjectNamespace(project luciConfig.ProjectName) string { |
24 return projectNamespacePrefix + string(project) | 31 return projectNamespacePrefix + string(project) |
25 } | 32 } |
26 | 33 |
27 // ProjectFromNamespace returns the current project installed in the supplied | 34 // ProjectFromNamespace returns the current project installed in the supplied |
28 // Context's namespace. | 35 // Context's namespace. |
29 // | 36 // |
30 // If the namespace does not have a project namespace prefix, this function | 37 // If the namespace does not have a project namespace prefix, this function |
31 // will return an empty string. | 38 // will return an empty string. |
32 func ProjectFromNamespace(ns string) config.ProjectName { | 39 func ProjectFromNamespace(ns string) luciConfig.ProjectName { |
33 if !strings.HasPrefix(ns, projectNamespacePrefix) { | 40 if !strings.HasPrefix(ns, projectNamespacePrefix) { |
34 return "" | 41 return "" |
35 } | 42 } |
36 » return config.ProjectName(ns[len(projectNamespacePrefix):]) | 43 » return luciConfig.ProjectName(ns[len(projectNamespacePrefix):]) |
37 } | 44 } |
38 | 45 |
39 // CurrentProject returns the current project based on the currently-loaded | 46 // CurrentProject returns the current project based on the currently-loaded |
40 // namespace. | 47 // namespace. |
41 // | 48 // |
42 // If there is no current namespace, or if the current namespace is not a valid | 49 // If there is no current namespace, or if the current namespace is not a valid |
43 // project namespace, an empty string will be returned. | 50 // project namespace, an empty string will be returned. |
44 func CurrentProject(c context.Context) config.ProjectName { | 51 func CurrentProject(c context.Context) luciConfig.ProjectName { |
45 if ns, ok := info.Get(c).GetNamespace(); ok { | 52 if ns, ok := info.Get(c).GetNamespace(); ok { |
46 return ProjectFromNamespace(ns) | 53 return ProjectFromNamespace(ns) |
47 } | 54 } |
48 return "" | 55 return "" |
49 } | 56 } |
50 | 57 |
51 // CurrentProjectConfig returns the project-specific configuration for the | 58 // CurrentProjectConfig returns the project-specific configuration for the |
52 // current project. | 59 // current project. |
53 // | 60 // |
54 // If there is no current project namespace, or if the current project has no | 61 // If there is no current project namespace, or if the current project has no |
55 // configuration, config.ErrInvalidConfig will be returned. | 62 // configuration, config.ErrInvalidConfig will be returned. |
56 func CurrentProjectConfig(c context.Context) (*svcconfig.ProjectConfig, error) { | 63 func CurrentProjectConfig(c context.Context) (*svcconfig.ProjectConfig, error) { |
57 return GetServices(c).ProjectConfig(c, CurrentProject(c)) | 64 return GetServices(c).ProjectConfig(c, CurrentProject(c)) |
58 } | 65 } |
59 | 66 |
60 // AllProjectsWithNamespaces scans current namespaces and returns those that | 67 // ActiveUserProjects returns a full list of all config service projects with |
61 // belong to LUCI projects. | 68 // a LogDog project configurations that the current user has READ access to. |
nodir
2016/05/19 17:17:21
s/a //
dnj (Google)
2016/05/19 20:10:46
Done.
| |
62 func AllProjectsWithNamespaces(c context.Context) ([]config.ProjectName, error) { | 69 func ActiveUserProjects(c context.Context) (map[luciConfig.ProjectName]*svcconfi g.ProjectConfig, error) { |
63 » var projects []config.ProjectName | 70 » allPcfgs, err := config.AllProjectConfigs(c) |
nodir
2016/05/19 17:17:21
I'd strongly recommend calling this function in a
dnj (Google)
2016/05/19 20:10:46
Agreed, and I'll put a TODO in, but this is not a
| |
64 » err := meta.NamespacesWithPrefix(c, projectNamespacePrefix, func(ns stri ng) error { | |
65 » » if proj := ProjectFromNamespace(ns); proj != "" { | |
66 » » » projects = append(projects, proj) | |
67 » » } | |
68 » » return nil | |
69 » }) | |
70 if err != nil { | 71 if err != nil { |
71 return nil, err | 72 return nil, err |
72 } | 73 } |
73 » return projects, nil | 74 |
75 » for project, pcfg := range allPcfgs { | |
nodir
2016/05/19 17:17:21
add a TODO to make acl check concurrent. Auth grou
dnj (Google)
2016/05/19 20:10:46
If this is actually a problem, I think we need to
| |
76 » » // Verify user access. This includes loading the project's confi g. | |
nodir
2016/05/19 17:17:21
it does not include that
dnj (Google)
2016/05/19 20:10:46
Done.
| |
77 » » if err := IsProjectReader(c, pcfg); err != nil { | |
78 » » » delete(allPcfgs, project) | |
nodir
2016/05/19 17:17:21
this makes me nervous. I'd rather create a separat
dnj (Google)
2016/05/19 20:10:46
Agree about parallel construction.
I thought abou
| |
79 | |
80 » » » // If it is a membership error, prune this project and c ontinue. | |
81 » » » // Otherwise, forward the error. | |
82 » » » if !IsMembershipError(err) { | |
83 » » » » // No configuration for this project, the config uration is invalid, or | |
84 » » » » // the user didn't have access. Remove it from t he list. | |
85 » » » » log.Fields{ | |
86 » » » » » log.ErrorKey: err, | |
87 » » » » » "project": project, | |
88 » » » » }.Errorf(c, "Failed to check project.") | |
89 » » » » return nil, err | |
90 » » » } | |
91 » » } | |
92 » } | |
93 » return allPcfgs, nil | |
74 } | 94 } |
OLD | NEW |